-
Notifications
You must be signed in to change notification settings - Fork 3
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
support React 18 #122
support React 18 #122
Conversation
src/useAnswersState.tsx
Outdated
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export const useAnswersState = (React as any).useSyncExternalStore === undefined && isServerEnvironment | ||
? useAnswersStateWithManualStoreSync : useAnswersStateWithReactStoreSync; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so useAnswersStateWithManualStoreSync
is only for react 17 SSR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does useAnswersStateWithManualStoreSync
work with react 18 as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also kind of curious if you read anything about what useSyncExternalStore is doing under the hood? If not then nbd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I was testing with startTransition
to try to simulate tearing issues, useAnswersStateWithManualStoreSync
doesn't work well with concurrent feature in react 18. Yup! useAnswersStateWithManualStoreSync
would be for react 17 SSR only since use-sync-external-store library can handle the client side rendering for 17 and automatically use the builtin useSyncExternalStore API for 18.
I didn't dig too much into what useSyncExternalStore does internally but it looks like it is a reform of useMutableSource if you are familiar with that
Have we tried looking at what react-redux is doing? It looks like we match up pretty closely? https://github.com/reduxjs/react-redux/blob/master/src/hooks/useSelector.ts |
After some digging into SSR, it look like component will NOT re-render so the logic to handle memoization of state selector and register subscription ( |
@@ -69,15 +101,15 @@ it('does not perform extra renders/listener registrations for nested components' | |||
expect(childStateUpdates).toHaveLength(0); | |||
|
|||
userEvent.click(screen.getByText('Search')); | |||
await pendingVerticalQuery; | |||
await act( async () => { await pendingVerticalQuery; }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
out of curiosity why are these acts necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember getting some warning about When testing, code that causes React state updates should be wrapped into act(...)
. I think we only mock the response of executeVerticalQuery
and not the function itself, so it still would send dispatch calls that trigger state updates? I wasn't getting the right number of times state listeners and updates without act(..) wrapper. We do this for the other tests, just not in this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh ok, maybe this is due to changing from react 17 to 18 with how batching works or something. I think I wrote this original test in a pretty weird way but I couldn't think of an easy way to change it here so eh
This pr updates answers-headless-react to support React 18 as well as 17.
use-sync-external-store
package for backwards-compatible with pre-18 versions (v17).From internal docs inupdated to useuse-sync-external-store
, the package does not offer much logic to support the case of server side rendering for react pre-18 versions. So, this pr update useAnswersState to be conditionally exported with eitheruseAnswersStateWithManualStoreSync
for SSR pre-18 oruseAnswersStateWithReactStoreSync
for everything else.use-sync-external-store
as is, without the manual handling, for all cases (for more info).isMountedRef
is used inuseAnswersStateWithReactStoreSync
to track when a component is unmounted and prevent the callback for handlling store changes from triggering (cause component update).@testing-library/react
,@types/react
)Note: will release an alpha version of this for the component lib.
J=SLAP-2095
TEST=manual&auto
Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17.
) which is expected.