0

I am getting a warning in my web app and have read a lot of posts about the issue. Unfortunately I have not managed to resolve my problem and hope someone might have some advice. From what I can tell I need to find a way of dispatching to the store in a useEffect. But my efforts so far have been unsuccessful.

The warning says:

index.js:1 Warning: Cannot update a component (Connect(TabMenuComponent)) while rendering a different component (ReactRedux.Consumer). To locate the bad setState() call inside ReactRedux.Consumer, follow the stack trace as described in https://reactjs.org/link/setstate-in-render

The stack trace further points me to this file. It points to line 30 which is the store.dispatch line:

export const AuthRoute = ({ component: Component, roles, computedMatch, ignoreRedirection, ...rest }) => (
  <Route exact {...rest} render={props => {
    return <ReactReduxContext.Consumer>
      {({ store }) => {
        const user = store.getState().appData.user;

        if (!user) {
          auth.setRedirectUrl(window.location.pathname);
          return <Redirect to={auth.loginUrl} />;
        }

        const redirectUrl = auth.getRedirectUrl();

        if (redirectUrl && !ignoreRedirection) {
          auth.removeRedirectUrl();
          return <Redirect to={redirectUrl} />;
        }

        if (roles && roles.length && !roles.some(neededRole => user.roles.some(userRole => userRole === neededRole))) {
          return <BaseLayout authError={stringKeys.error.unauthorized}></BaseLayout>;
        }

        store.dispatch({ type: "ROUTE_CHANGED", url: computedMatch.url, path: computedMatch.path, params: computedMatch.params })
        return <Component {...props} />;

      }}
    </ReactReduxContext.Consumer>;
  }
  } />
);

1 Answer 1

1

You are dispatching an action in the middle of a render which is not correct. What you should instead do is to create an HOC or a wrapper component to your input Component and dispatch the action once thee component is mounted

With class component wrapper:

class CompWithDispatch extends React.Component {
   componentDidMount()  {
    const { store, type, url, path, params } = this.props;
    store.dispatch({ type, url, path, params })
   }

   render() {
      const { store, type, url, path, params , component: Component,  ...rest} = this.props;
      return <Component {...rest} />
   }
}
 

With function component wrapper

const CompWithDispatch = (props) => {
    const { store, type, url, path, params, component:Component, ...rest } = props;
    useEffect(() => {
       store.dispatch({ type, url, path, params })
    }, []);
    return <Component {...rest} />

}

and use it like

export const AuthRoute = ({ component, roles, computedMatch, ignoreRedirection, ...rest }) => (
  <Route exact {...rest} render={props => {
    return <ReactReduxContext.Consumer>
      {({ store }) => {
        const user = store.getState().appData.user;

        if (!user) {
          auth.setRedirectUrl(window.location.pathname);
          return <Redirect to={auth.loginUrl} />;
        }

        const redirectUrl = auth.getRedirectUrl();

        if (redirectUrl && !ignoreRedirection) {
          auth.removeRedirectUrl();
          return <Redirect to={redirectUrl} />;
        }

        if (roles && roles.length && !roles.some(neededRole => user.roles.some(userRole => userRole === neededRole))) {
          return <BaseLayout authError={stringKeys.error.unauthorized}></BaseLayout>;
        }

        const additionalProps = { type: "ROUTE_CHANGED", url: computedMatch.url, path: computedMatch.path, params: computedMatch.params })
        return <CompWithDispatch {...additionalProps} {...props} component={component}/>;

      }}
    </ReactReduxContext.Consumer>;
  }
  } />
);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.