diff --git a/change/@fluentui-react-d174ae16-7e82-4494-b026-d256fe1eb378.json b/change/@fluentui-react-d174ae16-7e82-4494-b026-d256fe1eb378.json new file mode 100644 index 0000000000000..ef1dd5f363a40 --- /dev/null +++ b/change/@fluentui-react-d174ae16-7e82-4494-b026-d256fe1eb378.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "fix: re-implement early List rendering behind prop flag", + "packageName": "@fluentui/react", + "email": "seanmonahan@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react/etc/react.api.md b/packages/react/etc/react.api.md index c17aa0c86fd5e..996bd2f4c0f03 100644 --- a/packages/react/etc/react.api.md +++ b/packages/react/etc/react.api.md @@ -6781,6 +6781,7 @@ export interface IListProps extends React_2.HTMLAttributes | HT onRenderSurface?: IRenderFunction>; onShouldVirtualize?: (props: IListProps) => boolean; renderCount?: number; + renderEarly?: boolean; renderedWindowsAhead?: number; renderedWindowsBehind?: number; role?: string; diff --git a/packages/react/src/components/List/List.test.tsx b/packages/react/src/components/List/List.test.tsx index 2103060f32946..c98f52bc15186 100644 --- a/packages/react/src/components/List/List.test.tsx +++ b/packages/react/src/components/List/List.test.tsx @@ -135,6 +135,16 @@ describe('List', () => { expect(rows).toHaveLength(4); }); + + it('renders List correctly when `renderEarly={true}`', () => { + List.prototype.componentDidMount = jest.fn(); + + const onRenderCell = () => null; + const component = renderer.create(); + const tree = component.toJSON(); + + expect(tree).toMatchSnapshot(); + }); }); describe('if provided', () => { diff --git a/packages/react/src/components/List/List.tsx b/packages/react/src/components/List/List.tsx index c4bad1bb22995..0d224f99e2ab4 100644 --- a/packages/react/src/components/List/List.tsx +++ b/packages/react/src/components/List/List.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { Async, EventGroup, + canUseDOM, css, divProperties, findIndex, @@ -338,7 +339,7 @@ export class List extends React.Component, IListState> public componentDidMount(): void { this._scrollElement = findScrollableParent(this._root.current) as HTMLElement; this._scrollTop = 0; - this.setState(this._updatePages(this.props, this.state)); + this.setState({ ...this._updatePages(this.props, this.state), hasMounted: true }); this._measureVersion++; this._events.on(window, 'resize', this._onAsyncResize); @@ -491,7 +492,8 @@ export class List extends React.Component, IListState> nextProps.items !== this.props.items || nextProps.renderCount !== this.props.renderCount || nextProps.startIndex !== this.props.startIndex || - nextProps.version !== this.props.version + nextProps.version !== this.props.version || + (!previousState.hasMounted && this.props.renderEarly && canUseDOM()) ) { // We have received new items so we want to make sure that initially we only render a single window to // fill the currently visible rect, and then later render additional windows. diff --git a/packages/react/src/components/List/List.types.ts b/packages/react/src/components/List/List.types.ts index 2ee540b5b066f..772452b0edcb0 100644 --- a/packages/react/src/components/List/List.types.ts +++ b/packages/react/src/components/List/List.types.ts @@ -279,6 +279,13 @@ export interface IListProps extends React.HTMLAttributes | HTML * This is a performance optimization to let List skip a render cycle by not updating its scrolling state. */ ignoreScrollingState?: boolean; + + /** + * Whether to render the list earlier than the default. + * Use this in scenarios where the list is contained in a FocusZone or FocusTrapZone + * as in a Dialog. + */ + renderEarly?: boolean; } /** diff --git a/packages/react/src/components/List/__snapshots__/List.test.tsx.snap b/packages/react/src/components/List/__snapshots__/List.test.tsx.snap index 7a971b9e3de90..4ef35e5a0439b 100644 --- a/packages/react/src/components/List/__snapshots__/List.test.tsx.snap +++ b/packages/react/src/components/List/__snapshots__/List.test.tsx.snap @@ -1,5 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`List by default renders List correctly when \`renderEarly={true}\` 1`] = ` +
+
+
+`; + exports[`List renders List correctly 1`] = `