Skip to content

Fix react warning about causing a render during a render #22

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

Merged
merged 7 commits into from
Jun 10, 2021
Merged

Conversation

BenLorantfy
Copy link
Collaborator

@BenLorantfy BenLorantfy commented Oct 18, 2020

This PR does a few things:

  • Changes hooks to use useLayoutEffect instead of injecting during the render. This fixes the warning but comes with its own tradeoffs. For example, if an action is dispatched inside a useLayoutEffect inside a child component, it will be dispatched before the reducers/sagas have been injected.
  • Changes hooks to return booleans indicating whether or not the injection has completed. These can be used to mitigate the tradeoffs explained above. Components can check if the reducer/saga has been injected before rendering their children.
  • Adds a warning to the README recommending shouldHotReload be set to false inside the redux-devtools options. This is because otherwise redux-devtools will re-dispatch previous actions when a reducer is injected.
  • Updates the docs in a few other spots explaining these changes
  • Bumps the major version, as this could break apps that dispatch actions inside useLayoutEffect
  • Adds an example directory

New Feature

  • This PR also adds a createManager factory. Usage:
const BooksManager = createManager({ key: "books", name: "BooksManager", reducer: booksReducer, saga: booksSaga });

<BooksManager>
  <SomeOtherComponent />
</BooksManager>

The books manager will only render its children after the reducer and saga have been injected.

See this comment for more details
Closes #19

This commit does a few things:

- Changes hooks to use useLayoutEffect instead of injecting during the render.  This fixes the warning but comes with its own tradeoffs.  For example, if an action is dispatched inside a useLayoutEffect inside a child component, it will be dispatched before the reducers/sagas have been injected.
- Changes hooks to return booleans indicating whether or not the injection has completed. These can be used to mitigate the tradeoffs explained above.  Components can check if the reducer/saga has been injected before rendering their chilldren.
- Adds a warning to the README recommending `shouldHotReload` be set to false inside the redux-devtools options.  This is because otherwise redux-devtools will re-dispatch previous actions when a reducer is injected.
- Updates the docs in a few other spots explaining these changes
- Bumps the major version, as this could break apps that dispatch actions inside useLayoutEffect
@danielrob
Copy link

Question:
Would using useSelector straight after useInjectReducer in the same component in this PR still work? E.g.

useInjectReducer("injectedDomain", reducer); 
const xyz = useSelector(state => state.injectedDomain.xyz);

I'm not sure how late useLayoutEffect is deferring the domain injection?

@BenLorantfy
Copy link
Collaborator Author

BenLorantfy commented Oct 21, 2020

That should still work but I'll add a test for it

Actually I think the domain might be undefined the first time, I'll write a test to check

@danielrob
Copy link

danielrob commented Oct 21, 2020

If not I think this lib is headed towards a choice between HOC, or DIY wrapper using hooks api, or as you said, a factory to create your wrapper too. But a pure hooks approach just seems dead in the water unless one is willing to accept all the caveats.

@julienben
Copy link
Member

julienben commented Jan 5, 2021

I agree with @danielrob. In my team we didn't want to deal with the caveats (and we felt like using useLayoutEffect is a bit too hacky) so we switched to using the HOC only. We created our own HOC which handles both reducer and saga injection.

I'm still happy to review this PR if you'd like to merge and release it but it does have an additional caveat that needs to be handled: The isInjected mechanism doesn't take into account the different saga injection modes. (IMO, removing the saga injection modes is the best way to deal with this. I haven't seen anyone use them.)

@dathacky
Copy link

Niceeee

@jwinn jwinn self-requested a review April 26, 2021 15:05
Copy link

@jwinn jwinn left a comment

Choose a reason for hiding this comment

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

LGTM 👍 I don't have the ability to test locally right now, but this looks good.

@BenLorantfy
Copy link
Collaborator Author

BenLorantfy commented May 30, 2021

@julienben Do you want to review this before I merge it? I've removed the mode parameter from useInjectSaga (it now uses the COUNT mode which was introduced in PR #24 ) as well as add a new API called createManager. I also added an example app.

image

@BenLorantfy BenLorantfy merged commit 8dac91d into dev Jun 10, 2021
@BenLorantfy
Copy link
Collaborator Author

@julienben I merged but feel free to still review if you find some time

@BenLorantfy BenLorantfy deleted the bug/19 branch November 22, 2022 12:55
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.

5 participants