【问题标题】:Can only update a mounted or mounting component error. Conditional rendering只能更新挂载或挂载组件错误。条件渲染
【发布时间】:2018-05-03 20:48:19
【问题描述】:

所以我有一个登录页面,它将用户定向到配置文件页面,在该页面中发出异步请求以检索在 componentDidMount 事件中启动的用户 ID 号。得到结果后,我在 id 上设置状态并检索到数据。

import React, { Component } from 'react';
import {Navbar} from 'react-materialize';
import {Link, Redirect} from 'react-router-dom';
import helper from '../utils/helper';
import axios from 'axios';
import logo from '../logo.svg';
import '../App.css';

class Profile extends Component {
  constructor(props){
    super(props);
    this.state = {id: null, loggedIn: true};
       this.logOut = this.logOut.bind(this);

  }

  componentDidMount(){
    axios.get('/profile').then((results) => {
      if(!this._unmounted) {
        this.setState({id: results.data})
      }      
    })
  }

  logOut(event){
    axios.post('/logout').then((results) => {
      console.log(results);
    })
    this.setState({loggedIn: false});
  }

  render() {
    if(!this.state.loggedIn){
      return <Redirect to={{pathname: "/"}}/>
    }
    if(this.state.id == null){
      return <Redirect to={{pathname: "/login"}} ref="MyRef" />
    }

    return (
      <div>
        <Navbar brand='WorldScoop 2.0' right>
          <ul>
            <li><Link to="#" onClick={this.logOut}>Logout</Link></li>   
          </ul>
        </Navbar>
        <h1>Profile Page</h1>
        <h2>Welcome {this.state.id} </h2>
      </div>
    )
  }
}
export default Profile;

我正在努力使某人不能只在 url 中键入“/profile”路径并被带到个人资料页面。为此,我尝试根据是否从正确的登录身份验证中检索到 id 进行条件渲染。这就是为什么如果您注意到

if(this.state.id == null){
  return <Redirect to={{pathname: "/login"}} ref="MyRef" />
}

如果用户不提供电子邮件和密码,这会将用户重定向回登录页面。我已尝试确保我的配置文件组件在收到数据后安装和卸载,但我仍然不断收到错误消息: 只能更新已安装或正在安装的组件。当组件“卸载”时我很困惑。

【问题讨论】:

  • 您的代码当前是否将用户重定向到 /login?
  • 是的,所以即使我添加了用户凭据,我也会被重定向回 /login 并出现相同的错误。出于某种原因,this.setState({id: results.data})。没有使用检索到的用户 id 设置状态。我只在添加条件 if(this.state.id == null){ return } 时遇到这个问题
  • 是的,那是因为您的渲染方法正在解析,因此在您的 axios 调用完成之前重新路由您

标签: javascript reactjs asynchronous conditional-rendering react-lifecycle


【解决方案1】:

如果你想通过this._isunmounted检查组件是挂载还是卸载,你应该在componentWillUnmount中设置为true。

componentWillUnmount() {
   this._isunmounted = true;
}

【讨论】:

【解决方案2】:

render 方法正在解析,因此在您的 axios 调用完成之前重新路由您,因此解决方案是在您的调用完成之前不更改位置,通常使用加载指示器。此外,我将生命周期挂钩从 didMount 更改为 willMount,因此状态将在渲染之前反映。

import React, { Component } from 'react';
import {Navbar} from 'react-materialize';
import {Link, Redirect} from 'react-router-dom';
import helper from '../utils/helper';
import axios from 'axios';
import logo from '../logo.svg';
import '../App.css';

class Profile extends Component {
  constructor(props){
    super(props);
    this.state = {id: null, loggedIn: true, loading: false};
       this.logOut = this.logOut.bind(this);

  }

  componentWillMount(){
    this.setState({ loading: true });
    axios.get('/profile')
     .then((results) => {
         // usually data is an object so make sure results.data returns the ID
         this.setState({id: results.data, loading: false})
      })
     .catch(err => {
         this.setState({ loading: false, id: null })
      })
  }

  logOut(event){
    axios.post('/logout').then((results) => {
      console.log(results);
    })
    this.setState({loggedIn: false});
  }

  render() {
    if(!this.state.loggedIn){
      return <Redirect to={{pathname: "/"}}/>
    }
    if (this.state.loading) return <div>loading...</div>
    if(this.state.id == null){
      return <Redirect to={{pathname: "/login"}} ref="MyRef" />
    }

    return (
      <div>
        <Navbar brand='WorldScoop 2.0' right>
          <ul>
            <li><Link to="#" onClick={this.logOut}>Logout</Link></li>   
          </ul>
        </Navbar>
        <h1>Profile Page</h1>
        <h2>Welcome {this.state.id} </h2>
      </div>
    )
  }
}
export default Profile;

【讨论】:

  • 我要试试这个,Loader是你自己做的组件吗?
  • 是的,如果您没有,请使用&lt;div&gt;loading...&lt;/div&gt;
  • 您的答案部分有效,我将尝试更多。我可以使用用户凭据登录,但是当我尝试“作弊”并在 url 中输入“/profile”路径时,它只会将我带到“加载”div 并停留在那里。但是谢谢你让我更近了一步!我感觉这也是一个加载问题。
  • 我添加了一个 catch 以防 API 返回类似 404 的错误,因此您永远不会卡在正在加载的 div 上。
  • 刚刚看到你上面的catch promise,我一定是忽略了!我很抱歉。感谢您的帮助,我以后会开始更加关注错误处理
【解决方案3】:

我已成功删除错误消息:“只能更新已安装或正在安装的组件”,方法是使用 window.location.replace()。

render() {
   window.location.replace(`/profile`); // This is how to redirect 
   return (null);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-26
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 2017-08-12
    • 2014-04-19
    相关资源
    最近更新 更多