From 14350b1c23ac982278abac59331ca054fec9bf45 Mon Sep 17 00:00:00 2001 From: Sean Monahan Date: Mon, 27 Feb 2023 22:31:09 +0000 Subject: [PATCH 1/3] fix: re-implement early List rendering behind a prop flag Previously this had been implemented as the new default behavior for List rendering but it broke advanced rendering scenarios like TilesList. This PR puts the early render behavior behind a flag to ensure that existing controls like TilesList will continue to function with no changes while experiences that need the new behavior can opt into it. --- packages/react/src/components/List/List.test.tsx | 10 ++++++++++ packages/react/src/components/List/List.tsx | 6 ++++-- packages/react/src/components/List/List.types.ts | 7 +++++++ .../components/List/__snapshots__/List.test.tsx.snap | 11 +++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) 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 d2b922663770d..58ebb291fba93 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`] = `
Date: Mon, 27 Feb 2023 22:35:18 +0000 Subject: [PATCH 2/3] changes files --- ...luentui-react-d174ae16-7e82-4494-b026-d256fe1eb378.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-d174ae16-7e82-4494-b026-d256fe1eb378.json 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" +} From a4a4581053abcfc725e6c69db42d30d3958614bb Mon Sep 17 00:00:00 2001 From: Sean Monahan Date: Mon, 27 Feb 2023 23:03:47 +0000 Subject: [PATCH 3/3] update API snapshot --- packages/react/etc/react.api.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react/etc/react.api.md b/packages/react/etc/react.api.md index eb40c50e0161f..32cb60bd6a3df 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;