Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(react): fix compatibility issues with React 18 #969

Merged
merged 5 commits into from
May 10, 2022
Merged

Conversation

sarahdayan
Copy link
Member

@sarahdayan sarahdayan commented May 9, 2022

This introduces a documented solution to make autocomplete-js work with React 18.

This solution is a workaround. We need to work on better support for these new React APIs, but this temporary solution allows React 18 users to work with Autocomplete in a non-breaking way.$

fixes #950

Documented solution

React 18 no longer recommends using ReactDOM.render, users should now be creating a Root object with ReactDOM.createRoot, then use the render function on this object.

In Autocomplete, we don't render in panelContainer but in an inner container (.aa-Panel). Unlike container and panelContainer, this element is not injectable and is only accessible in render (it's the second parameter root). Therefore, we can't create the React Root object ahead of time and pass its render function to renderer.render.

The solution passes renderer.createElement and renderer.Fragment, and implements render instead of passing renderer.render. We create a React Root object with createRoot(root) and store it in a ref to reuse it whenever we need to render.

The root element can change (notably when switching between non-detached and detached mode) so we need to create a new React Root when it does. We do this by tracking root in a ref and comparing it whenever render is called.

Types

React 18's createElement was no longer assignable to Pragma because of two issues:

  • ComponentChild was assignable to object (this comes from Preact) while ReactNode isn't.
  • ReactNode is assignable to ReactPortal which has a mandatory key that VNode didn't have.

Regarding object, we don't need/use it internally so I think it's fine to drop it.

Regarding VNode, I checked the latest version of the type in the Preact codebase and it looks like key is now mandatory at the root level (since preactjs/preact#1447). However I don't think there's ever been an optional key in VNode.props so I assumed this was added here by mistake instead of at the root (cc @francoischalifour) and I removed it.

Type check is passing and our React InstantSearch Hooks example (using React 17) doesn't show type errors, so it looks fine.

Warning

Since this solution requires not passing renderer.render and implementing render instead, the following warning shows up:

Capture d’écran 2022-05-09 à 18 49 32

This warning is useful for React 17 and Vue users who implemented a custom renderer before 1.6.0 but it will become annoying for React 18 users. I don't think we can detect the React version from createElement or Fragment, so I don't think we can selectively display the warning.

React 18 will increasingly become the top users of the renderer API so I believe it makes sense to cater to them. It comes at the expense of delivering this bit of advice, but it's not causing any issues so I think it's preferable drop it for now.

As recommended by @Haroenv, we can recommend React 18 users to pass an empty function to renderer.render to dismiss the warning.

@codesandbox-ci
Copy link

codesandbox-ci bot commented May 9, 2022

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 54e6718:

Sandbox Source
algolia/autocomplete Configuration
algolia/autocomplete Configuration
@algolia/autocomplete-example-playground Configuration
algolia/autocomplete Configuration
@algolia/autocomplete-example-react-renderer Configuration
@algolia/autocomplete-example-starter-algolia Configuration
algolia/autocomplete Configuration
@algolia/autocomplete-example-reshape Configuration
@algolia/autocomplete-example-vue Configuration
upbeat-bell-m9thse Issue #950
competent-forest-68oo3p Issue #950

@sarahdayan sarahdayan marked this pull request as ready for review May 9, 2022 17:06
Copy link
Member

@dhayab dhayab left a comment

Choose a reason for hiding this comment

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

Cool workaround, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Custom Renderer in React 18
3 participants