最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Render methods should be a pure function of props and state - Stack Overflow

programmeradmin2浏览0评论

I am receiving the error of Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state..

It appears that it is because of this code

const LoginAuth = () => {
  navigate(routes.INDEX);
  return null;
};

removing navigate(routes.INDEX); stops the error.

What is wrong with the code? Should I be using another method to redirect an authUser? Any help is appreciated.

It is a part of

import React from 'react';
import { navigate } from 'gatsby';

import AuthUserContext from './AuthUserContext';
import withAuthentication from './withAuthentication';

import Layout from './Layout';
import LoginForm from './LoginForm';    
import * as routes from '../../constants/routes';

const LoginAuth = () => {
  navigate(routes.INDEX);
  return null;
};

const LoginPage = () => (
  <Layout>
    <Transition>
      <AuthUserContext.Consumer>
        {authUser => (authUser ? <LoginAuth /> : <LoginNonAuth />)}
      </AuthUserContext.Consumer>
    </Transition>
  </Layout>
);

const LoginNonAuth = () => <LoginForm />;

export default withAuthentication(LoginPage);

I am receiving the error of Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state..

It appears that it is because of this code

const LoginAuth = () => {
  navigate(routes.INDEX);
  return null;
};

removing navigate(routes.INDEX); stops the error.

What is wrong with the code? Should I be using another method to redirect an authUser? Any help is appreciated.

It is a part of

import React from 'react';
import { navigate } from 'gatsby';

import AuthUserContext from './AuthUserContext';
import withAuthentication from './withAuthentication';

import Layout from './Layout';
import LoginForm from './LoginForm';    
import * as routes from '../../constants/routes';

const LoginAuth = () => {
  navigate(routes.INDEX);
  return null;
};

const LoginPage = () => (
  <Layout>
    <Transition>
      <AuthUserContext.Consumer>
        {authUser => (authUser ? <LoginAuth /> : <LoginNonAuth />)}
      </AuthUserContext.Consumer>
    </Transition>
  </Layout>
);

const LoginNonAuth = () => <LoginForm />;

export default withAuthentication(LoginPage);
Share Improve this question asked Oct 21, 2018 at 4:59 DarrenDarren 2,29010 gold badges48 silver badges104 bronze badges 6
  • 1 Your LoginAuth is a function that should return additional stuff to render to the page and you call navigate directly in it. Are you trying to navigate as soon as the component is rendered? – Rory Commented Oct 21, 2018 at 5:22
  • Hey @rory_za. Yes, if the authUser is authenticated the page renders LoginAuth, else LoginNonAuth is rendered. Therefore, if the user authenticates using the <LoginForm /> or is currently authenticated, the user is immediately redirected (naviagate()) to another page. – Darren Commented Oct 21, 2018 at 5:26
  • It possibly can be solved by putting side effects (navigate) into componentDidMount. Please, let know if this works. – Estus Flask Commented Oct 21, 2018 at 6:37
  • Hey @estus. Yes, wrapping in a stateful container with navigate in componentDidMount did the trick. – Darren Commented Oct 21, 2018 at 7:13
  • Thanks @estus. If you wanted to add to an answer, I'll accept. If not, I'll do so - thought you may want the reputation points. – Darren Commented Oct 21, 2018 at 7:15
 |  Show 1 more comment

2 Answers 2

Reset to default 12

Stateless functional components are expected to be pure functions, i.e. contain no side effects, while navigate() provides side effects.

Side effects are supposed to be applied after the component is mounted, that's the purpose of componentDidMount hook.

It should be:

class LoginAuth extends Component {
  componentDidMount() {
    navigate(routes.INDEX);
  }

  render() {
    return null;
  }
}

With the introduction of stateful functional components, side effects belong to useEffect hook:

const LoginAuth = () => {
  useEffect(() => {
    navigate(routes.INDEX);
  }, []);

  return null;
};

The problme is before mount the component history.push is called here. I realized after that and used useEffect inside the logic then it working without any issue.

Error:

const Component = ({
    classes,
    isAuthenticated
}) => {

    const history = useHistory()


    if (isAuthenticated === true) {
        history.push(DASHBOARD_ROUTE)
    }

    return null
}

Solution:

const Component = ({
    classes,
    isAuthenticated
}) => {

    const history = useHistory()

    useEffect(() => {
        if (isAuthenticated === true) {
            history.push(DASHBOARD_ROUTE)
        }
    }, [])

    return null
}
发布评论

评论列表(0)

  1. 暂无评论