在反应渲染之前总是调用componentDidMount

时间:2020-08-27 18:59:28

标签: reactjs

我是React世界的新手,我试图从axios调用中获取用户数据,并试图在执行react的渲染之前获取数据。

我怎么称呼这个组件

<Route path="/users" render={(props) => <User {...props}/>} />

这是我的组件类

class User extends React.Component {

    constructor(props) {
        super(props);
        this.state = { authenticated: false }
        this.getCurrentUser = this.getCurrentUser.bind(this);
    }

    componentDidMount(){
        console.log("componentDidMount");
        this.getCurrentUser();
    }

    getCurrentUser(){
        Api.getCurrentUser().then(response => {
        if (response) {
            console.log(response.data.username);
            this.setState({authenticated: true});
        }
      }).catch(error =>{
          this.setState({authenticated: false});
       }
    }

    render() {

        console.log(this.state.authenticated);
        if (this.state.authenticated === false) {
            return <Redirect to={{ pathname: '/login' }}/>
        }
        return (
            <div><Page /> <div>
        );
    }
}

export default User;

console.log顺序为

false        
componentDidMount
user_one
Warning: Can't perform a React state update on an unmounted component. This is a no-op

该警告之所以有意义,是因为反应已经使我重定向到登录名,因此未安装用户组件。

我不明白为什么在渲染之前未调用componentDidMount,因为它假定通过this.setState()更改defaultState。

我在这里想念什么?

2 个答案:

答案 0 :(得分:1)

ComponentDidMount按照您描述的方式工作。它在呈现组件后立即运行。您可以做的是用一个具有API调用的父组件包装Component,然后将isAuthenticated作为props传递给。

Docs for reference

答案 1 :(得分:0)

正如@ user2079976正确指出的那样,您对componentDidMount的使用是正确的,并且符合预期的使用方式,但是我认为由于代码执行工作流程,您可能会得到错误的印象。

问题原因

此问题/警告通常与正在更新已卸载的组件有关,在这种情况下,很可能是在api返回结果之前发生的重定向。

更多详细信息:

由于没有完整的代码示例,我不得不猜测您设置中的一些变量,而且正如您所解释的,我无法在JsFiddle上得到确切的问题(我认为JsFiddle / react.prod吞噬了警告消息),但是...我将尝试更新此fiddle,以尽我所能地通过注释进行解释。

// at render this is still false as `state.authenticated` 
// only becomes true after the redirect.
// the code then redirects.... 
// then updates the not yet mounted component & its state 
// which is causing the warning
if (this.state.authenticated === false) {
    return (<Redirect to={{ pathname: '/about' }}/>)
}
return (<div>On Home</div>);

可能的解决方案

  • 您应该将身份验证/已登录(状态)设置为更高级别/父级组件,并让路由器决定将用户发送到哪里。

  • 我们已经在一个应用程序中使用了这个确切的示例(这是上述建议的实现)。它非常适合身份验证类型的工作流程,并且直接来自您正在使用的Router lib的文档:P https://reactrouter.com/web/example/auth-workflow