【问题标题】:React js state and lifecycleReact js 状态和生命周期
【发布时间】:2018-10-18 10:28:05
【问题描述】:
componentDidMount() {
    const user = auth.getCurrentUser();
    this.setState({ user });
  }

我有这个代码,我想this.setState({ user });需要一点时间,如果我想做一些检查的话就像

<Route
              path="/foo"
              render={props =>
                this.state.user ? (
                  <Bar {...props} />
                ) : (
                  <Redirect to="/login" />
                )
              }
            />

刷新页面时,用户一开始总是为空。什么是正确的解决方案?我需要在constructor 设置状态吗?还是我做错了什么?

我的帐户被一些反对票问题阻止了,有趣的是我必须重新编辑它们,即使我已经有接受的答案。我不明白这样做有什么意义。我很沮丧这个stackoverflow系统。

现在,我基本上什么也做不了,只能继续编辑我的问题,而且它们都已得到解答。这太荒谬了!!!

【问题讨论】:

  • “我需要在构造函数中设置状态吗?”,你试过了吗,结果如何?
  • 使用回调或使用异步/等待。还将 this.setState({ user }) 更改为 this.setState({ user: user });
  • @NguyễnThanhTú 是的,我做到了。如果我在constructor 中设置状态,只是想知道最佳做法是什么
  • @parth 与异步和等待无关。该功能没有承诺。这个this.setState({ user });是有效的js代码
  • @AndySong 我想我知道你想做什么。那么,这篇文章可能会有所帮助:tylermcginnis.com/react-router-protected-routes-authentication

标签: javascript reactjs


【解决方案1】:

是的,你应该在构造函数中初始化你的状态。

React docs example

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

【讨论】:

  • 嗨,我知道,它正在工作。所以我在componentDidMount 做的事情是错的,对吗?当我进行 api 调用时,我们通常在 componentDidMount 中进行,当我们立即进行一些检查时,我应该在 constructor 中进行吗?
【解决方案2】:

刷新页面时,开头的用户总是为空

@Shubham Khatri 确实解释得很好,简而言之,只是因为render() 函数在componentDidMount() 之前被调用,因此user 始终为空。

看看这个:React lifecycle methods diagram

如您所见,setState 的正确位置应该是 contructor(),因为它在 render() 之前被调用。

但是,对于 api 调用,为什么 componentDidMount 是更好的地方?为什么 我们不是全部设置在constructor吗?

我知道你在谈论这个:https://reactjs.org/docs/faq-ajax.html。该文档确实说:您应该在 componentDidMount 生命周期方法中使用 AJAX 调用填充数据。这样您就可以在检索数据时使用setState 更新您的组件。

但是,in another place,他们说:

您可以立即致电setState()componentDidMount()。它会 触发额外的渲染,但它会在浏览器之前发生 更新屏幕。这保证即使render() 将 在这种情况下被调用两次,用户不会看到中间 状态。谨慎使用此模式,因为它通常会导致 性能问题。 在大多数情况下,您应该能够分配 constructor() 的初始状态。 但是,它可以是 当您需要测量时,对于模态和工具提示等情况是必需的 渲染前的 DOM 节点取决于其大小或 位置。

...也适用于您需要进行身份验证的情况,因为此过程取决于 user 的值(作为您的设计)。

【讨论】:

    【解决方案3】:

    您的代码中的问题是,componentDidMount 在渲染之后被调用,并且当您的用户详细信息被获取并存储在状态时,您的组件已准备好重定向到 /login,因为用户不可用。要解决此问题,您需要在初始渲染之前获取 user 详细信息,因此 constructor 是执行此操作的理想位置

    constructor(props) {
       super(props);
       this.state = {
           user: auth.getCurrentUser()
       }
    }
    

    【讨论】:

    • 然而,对于 api 调用,为什么 componentDidMount 是更好的地方?为什么我们不在constructor做所有设置?
    • @AndySong 请检查这个答案stackoverflow.com/questions/47392910/…
    【解决方案4】:

    状态进入构造函数,但前提是你需要一个构造函数(例如:初始化标志)。如果你不需要构造函数,你可以在外面初始化状态:

    class MyComponent extends Component {
        state = { myState = [] }
    
        render() {
            const { myState } = this.state
            return (...)
        }
    }
    

    【讨论】:

      【解决方案5】:

      您应该使用constructor() 来初始化状态,componentDidMount() 用于调用函数,componentWillReceiveProps() 用于setState。

        constructor(props) {
          super(props);
          this.state = {
            firstName: "",
            lastName: ""
          };
        }
      
        componentDidMount() {
          this.props.userProfile();
        }
      
        componentWillReceiveProps(nextProps, prevProps) {
          this.setState({
            firstName: nextProps.user.firstName,
            lastName: nextProps.user.lastName
          });
        }
      

      【讨论】:

        猜你喜欢
        • 2018-06-30
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多