Skip to content

fix(react): keep PathnameProvider mounted so changing userId doesn't change hook count (#384)#704

Open
crossi-dev wants to merge 1 commit into
RBND-studio:mainfrom
crossi-dev:fix/384-flowsprovider-userid-change
Open

fix(react): keep PathnameProvider mounted so changing userId doesn't change hook count (#384)#704
crossi-dev wants to merge 1 commit into
RBND-studio:mainfrom
crossi-dev:fix/384-flowsprovider-userid-change

Conversation

@crossi-dev

Copy link
Copy Markdown

Fixes #384

Problem

FlowsProvider early-returns when userId isn't set yet:

if (!isProps(props)) return props.children;
return <PathnameProvider><FlowsProviderInner {...props} /></PathnameProvider>;

So while userId is null the children render outside PathnameProvider. When userId then changes to a string, PathnameProvider (which has useState/useEffect) is mounted into the tree at the same parent fiber for the first time — the render now runs more hooks than the previous one, and React throws "Rendered more hooks than during the previous render."

Fix

Keep PathnameProvider mounted at a stable position on every render, and switch the inner content instead:

return (
  <PathnameProvider>
    {isProps(props) ? <FlowsProviderInner {...props} /> : props.children}
  </PathnameProvider>
);

PathnameProvider's hooks now run on every render regardless of userId, so the hook count never changes across the null → string transition.

Verified

pnpm test
  workspaces/react   Test Suites: 1 passed   Tests: 3 passed
  workspaces/shared  Test Suites: 4 passed   Tests: 107 passed
  exit code: 0

I added 3 regression tests covering mount-with-userId, mount-without then set userId, and the reverse. The workspaces/react package had no component-test harness yet, so the PR also adds react-dom + @types/react-dom (devDeps) and "types": ["jest"] to its tsconfig — the minimal wiring needed to render the provider in a test. Happy to drop the test + that wiring and keep just the 4-line fix if you'd prefer a leaner diff.


Came across flows-sdk and noticed #384 had been open a while, so I fixed it. No strings attached — I'm with Choreless and we like contributing real fixes to projects we use. If it's useful and you ever want a hand with something larger, happy to help.

— Charles

Previously FlowsProvider returned props.children directly (outside
PathnameProvider) when userId was null. When userId later changed to a
string, PathnameProvider was inserted into the tree for the first time,
causing React to throw "Rendered more hooks than during the previous
render" because the component subtree structure changed under the same
parent fiber.

Fix: always render PathnameProvider so it is stable in the tree;
conditionally render FlowsProviderInner vs raw children inside it.

Closes RBND-studio#384
@VojtechVidra

Copy link
Copy Markdown
Member

Hi @crossi-dev and thanks for the PR! I do like the idea, keeping the React component tree the same with or without the userId would prevent the app from rerendering completely after SSR/SSG hydration.

However this PR seems incomplete to me. The <FlowsContext.Provider> is still rendered only with the userId defined. As a result I don't think the issue is actually solved.

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.

FlowsProvider throw error when changing userId

2 participants