Skip to content
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

[v6] Cannot update a component from inside the function body of a different component. #7199

Closed
ellisio opened this issue Mar 18, 2020 · 7 comments

Comments

@ellisio
Copy link

ellisio commented Mar 18, 2020

I'm tinkering with the v6 Alpha release and am running into the following console warning (see facebook/react#18178 for more information):

index.js:1 Warning: Cannot update a component from inside the function body of a different component.
    in Navigate (at Authenticated.js:27)
    in Unknown (at App.js:26)
    in Route (at App.js:26)
    in Routes (at App.js:23)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:22)
    in ErrorBoundary (at App.js:21)
    in App (at src/index.js:59)
    in PersistGate (at src/index.js:58)
    in Provider (at src/index.js:57)

In v5, I had the following component:

import React from 'react';
import { Redirect } from 'react-router-dom';

export default ({ children }) => {
  const isAuthenticated = useSelector(state => !!state.auth.userId);

  if (!isAuthenticated) {
    return <Redirect to="/auth/login" />;
  }

  return children;
};

Which is implemented via:

<Switch>
  <Route exact component={AuthLogin} path="/auth/login" />
  <Authenticated>
    <Route exact component={Dashboard} path="/" />
  </Authenticated>
</Switch>

In v6, I have modified that component to be:

import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';

export default () => {
  const isAuthenticated = useSelector(state => !!state.auth.userId);

  if (!isAuthenticated) {
    return <Navigate to="/auth/login" />;
  }

  return <Outlet />;
};

Which is implemented via:

<Routes>
  <Route exact element={<AuthLogin />} path="/auth/login" />
  <Route element={<Authenticated />} path="/">
    <Route exact element={<Dashboard />} path="/" />
  </Route>
</Routes>

When navigating to http://localhost:3000, I am properly redirected to http://localhost:3000/auth/login, but receive the aforementioned console warning.

Is there a different way I should be doing this with v6?

@timdorr
Copy link
Member

timdorr commented Mar 18, 2020

This is a new warning in React 16.13.

I think the problem is we're issuing the effect of navigation in the Navigate component directly during rendering, not inside of a useEffect:

https://github.com/ReactTraining/react-router/blob/c5fa32954e2744c8b52aa8d4dbe2a885d2133428/packages/react-router/index.js#L98-L102

That alters the one single state value we maintain all the way up in Router:

https://github.com/ReactTraining/react-router/blob/c5fa32954e2744c8b52aa8d4dbe2a885d2133428/packages/react-router/index.js#L200-L205

Hence, you hit the new warning that React now watches for. Again, I think the effect hook will help with this.

@joejordan
Copy link

I have this error appearing on withRouter-wrapped components using react-router-dom 5.1.2. The stack trace is ridiculous on this new warning but it appears thus far only where I have wrapped a functional component.

@baurine
Copy link

baurine commented Mar 31, 2020

react-router version: 6.0.0-alpha.2

With react 16.13.0, I get the same error message:

Warning: Cannot update a component from inside the function body of a different component.

after upgrading to 16.13.1, the error message changes to:

Warning: Cannot update a component (`Router`) while rendering a different component (`Routes`). To locate the bad setState() call inside `Routes`, follow the stack trace as described in https://fb.me/setstate-in-render.

screenshot:

image

@baurine
Copy link

baurine commented Apr 2, 2020

Hi guys, do you have any plan to have a look at this issue?

@timdorr
Copy link
Member

timdorr commented Apr 2, 2020

See the linked PR: #7203

mjackson added a commit that referenced this issue Apr 3, 2020
- Removes <Redirect>
- Removes support for { redirectTo } in useRoutes()
- Warns if navigate() is used during the initial render
- Warns when <Navigate> is used on the initial render in <StaticRouter>

This began as a discussion on GitHub (see #7203). Essentially we need to
treat all navigation as a side effect, which means it needs to happen in
a useEffect. If people need v5's <Redirect> functionality (when it was
used in the route config inside a <Switch>), they either need to a) do
the redirect on the server (the best solution) or b) render a <Navigate>
on the initial render. However, (b) will only show the new route on the
subsequent render.

This should also eliminate warnings in the dev-experimental builds.

Closes #7203
Fixes #7199
@mjackson
Copy link
Member

mjackson commented Apr 4, 2020

This was fixed in cbcd398

@mjackson mjackson closed this as completed Apr 4, 2020
@mjackson
Copy link
Member

mjackson commented Apr 4, 2020

Will be released shortly in 6.0.0-alpha.3 👍

@lock lock bot locked as resolved and limited conversation to collaborators Jun 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants