react-boilerplate / react-boilerplate-cra-template

:fire: Setup Create React App with React Boilerplate. Highly scalable & Best DX & Performance Focused & Best practices.
https://react-boilerplate.github.io/react-boilerplate-cra-template/
MIT License
1.87k stars 395 forks source link

useInjectReducer updates store, leading to warning "Cannot update a component (x) while rendering a different component..." #179

Open dungkhuc opened 2 years ago

dungkhuc commented 2 years ago

Description

We have 2 components, one is parent and one is child. Both components have its own slice. When the child component is rendered for the first time, a warning will be thrown in the console:

image

This is caused by useInjectReducer hook. My interpretation of the issue is that the hook make change to the store, affecting both the parent and the child component.

https://github.com/react-boilerplate/redux-injectors/blob/master/src/injectReducer.js#L69 image

This is briefly mentioned at the end in #54 , after it is closed.

This issue in react-redux seems to be related https://github.com/reduxjs/react-redux/issues/1640.

Steps to reproduce

  1. Create two components with separate injected reducers
  2. Nest one component in the other
  3. Start react app and navigate to route that render both component
  4. Check warning in the console.

Versions

Can-Sahin commented 2 years ago

hmm, I have no solution within this repo atm. I already removed redux-injectors lib out of this repo and implemented them manually since that repo is dead. But, it will take a while till I release this version (winter probably. Have no time in summer).

srivastavab commented 1 year ago

@Can-Sahin where is it available? How do I implement?

trinvh commented 1 year ago

Same issue. Waiting for a new release

dungkhuc commented 1 year ago

To others, I simply removed the injectors. This issue may cause some unexpected behaviors in the frontend.

Can-Sahin commented 1 year ago

https://github.com/International-Slackline-Association/slackmap-ui

I have been working on this. You can see the new setup I made without injectors npm package. I don't have free time yet to update this repo, but if anybody is interested in solving it on their own then take a look. It's straightforward and explicit. Its in src/store.

By the way, it uses RTK Query instead Saga. Plus, it's really a web app working if you need some project references :)

PaulSinghDev commented 1 year ago

Just chiming in that this issue seems to occur when using RTK's dispatcher within a NextJS SSR block. I have a simple app skeleton that I am building out. It is using the SSR block to set the nav links into the state depending on the URL parameters. There is nowhere in the app's components where the store is changed other than with an onClick handler.

When I transition from the first page to the next this warning appears. The only way I can make it go away is by removing the NavLinks component which is using useAppSelect to get the nav links from my state/store.

Example SSR Block:

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async () => {
    // Set the nav first so we can access on the 404 page
    store.dispatch(
      setNavigation({
        isRestaurant: false,
        navLinks: genericNavLinks.links,
        isOpen: false,
      })
    );

    // Check we have page data
    const pageData = pages.find((page) => page.slug === "/");
    if (!pageData) return { notFound: true };
    return { props: { ...pageData } };
  }
);

The NavDrawer component (has the dispatch):

const NavDrawer: React.FC<NavDrawerProps> = ({ testId, id, style }) => {
  const { isOpen } = useAppSelector(selectNavigation);
  const dispatch = useAppDispatch();

  const handleNavClose: React.MouseEventHandler<HTMLButtonElement> = () =>
    dispatch(setNavigationOpen(false));

  return isOpen ? (
    <>
      <Underlay onClick={handleNavClose} isActive={true} />
      <div
        data-testid={testId}
        style={style}
        className={styles.wrapper}
        id={id}
      >
        <NavDrawerHeader />
        <NavLinks />
        <NavDrawerFooter />
      </div>
    </>
  ) : (
    <MobileNavOpenButton />
  );
};

The NavLinks component (If I remove the selector from here the warning goes away):


const NavLinks: React.FC<NavLinksProps> = ({ testId, id }) => {
  const { navLinks } = useAppSelector(selectNavigation);
  return (
    <div className={styles.wrapper}>
      <ul role="list" data-testid={testId} className={styles.list} id={id}>
        {navLinks.map((link) => (
          <NavLink key={link.id} link={link} />
        ))}
      </ul>
    </div>
  );
};

This has been doing my head in for a few days now, any advice?