Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

feat(hooks): introduce <DynamicWidgets> #3216

Merged
merged 4 commits into from
Nov 30, 2021
Merged

Conversation

francoischalifour
Copy link
Member

@francoischalifour francoischalifour commented Nov 29, 2021

This adds the <DynamicWidgets> to the Hooks package. It's implemented on top of useDynamicWidgets.

<DynamicWidgets> is a widget that displays matching widgets based on by the corresponding settings of the index.

Changes

I upgraded React from 16 to 17 because it better supports Strict Mode and memory leaks warnings, which <DynamicWidgets> was prone to. I explain in details how it happens in useConnector.

Usage

function App(props) {
  return (
    <InstantSearch {...props}>
      <DynamicWidgets>
        <Panel header="Brands">
          <RefinementList attribute="brand" />
        </Panel>

        <Panel header="Categories">
          <Menu attribute="categories" />
        </Panel>

        <Panel header="Hierarchy">
          <HierarchicalMenu
            attributes={[
              'hierarchicalCategories.lvl0',
              'hierarchicalCategories.lvl1',
            ]}
          />
        </Panel>

        <Panel header="Price">
          <RangeInput attribute="price" />
        </Panel>
      </DynamicWidgets>
    </InstantSearch>
  );
}

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 29, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 69b6cd2:

Sandbox Source
react-instantsearch-app Configuration
routing-basic Configuration
algolia/react-instantsearch Configuration

@netlify
Copy link

netlify bot commented Nov 29, 2021

✔️ Deploy Preview for react-instantsearch ready!

🔨 Explore the source changes: a608a74

🔍 Inspect the deploy log: https://app.netlify.com/sites/react-instantsearch/deploys/61a4eb71f77d53000801c91b

😎 Browse the preview: https://deploy-preview-3216--react-instantsearch.netlify.app

Comment on lines +65 to +80
invariant(
React.Children.count(component.props.children) === 1,
`<DynamicWidgets> only supports a single component in nested components. Make sure to not render multiple children in a parent component.

Example of an unsupported scenario:

\`\`\`
<DynamicWidgets>
<MyComponent>
<RefinementList attribute="brand" />
<Menu attribute="categories" />
</MyComponent>
</DynamicWidgets>
\`\`\`
`
);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a new invariant that we don't yet have in the other flavors. It provides guidance on what to do in this scenario because React.Children.only throws a generic error when there are multiple children.

Comment on lines +34 to +56
// There are situations where InstantSearch.js may render widgets slightly
// after they're removed by React, and thus try to update the React state
// on unmounted components. React 16 and 17 consider them as memory leaks
// and display a warning.
// This happens in <DynamicWidgets> when `attributesToRender` contains a
// value without an attribute previously mounted. React will unmount the
// component controlled by that attribute, but InstantSearch.js will stay
// unaware of this change until the render pass finishes, and therefore
// notifies of a state change.
// This ref lets us track this situation and ignore these state updates.
if (shouldSetStateRef.current) {
const { instantSearchInstance, widgetParams, ...renderState } =
connectorState;

// eslint-disable-next-line @typescript-eslint/no-use-before-define
setState(renderState);
});
// eslint-disable-next-line @typescript-eslint/no-use-before-define
setState(renderState);
}
},
() => {
// We'll ignore the next state update until we know for sure that
// InstantSearch.js re-inits the component.
shouldSetStateRef.current = false;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the important part that avoids memory leaks warnings in React 16 and 17.

@netlify
Copy link

netlify bot commented Nov 29, 2021

✔️ Deploy Preview for react-instantsearch ready!

🔨 Explore the source changes: 69b6cd2

🔍 Inspect the deploy log: https://app.netlify.com/sites/react-instantsearch/deploys/61a624b2036654000854ba7d

😎 Browse the preview: https://deploy-preview-3216--react-instantsearch.netlify.app

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good!

@@ -150,19 +150,19 @@
},
{
"path": "packages/react-instantsearch/dist/umd/Dom.min.js",
"maxSize": "41.50 kB"
"maxSize": "42 kB"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react 17 increased this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

);
}

// @TODO: we swallow React act errors in this test because we're unable to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does wrapping in act not work because it's a separate component?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. I don't understand why it that case it errors.

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to merge as-is for now I think

@francoischalifour francoischalifour merged commit d99aea6 into master Nov 30, 2021
@francoischalifour francoischalifour deleted the feat/DynamicWidgets branch November 30, 2021 14:58
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants