【问题标题】:Setting state on componentDidMount()在 componentDidMount() 上设置状态
【发布时间】:2016-06-21 09:06:50
【问题描述】:

我知道在componentDidMount 上设置状态是一种反模式,并且应该在componentWillMount 上设置一个状态,但假设我想将li 标签数量的长度设置为一个状态。在这种情况下,我无法在componentWillMount 上设置状态,因为在该阶段可能没有安装li 标签。那么,这里最好的选择应该是什么?如果我将状态设置为componentDidMount 会好吗?

【问题讨论】:

  • 您是否根据某些道具(或数据)呈现li 标签?你能用data.length吗?
  • 简单地说。假设我有 4 个 li 标签,我想获取它们的数量,以便我的 maxNumber 状态应该是 4。但是,我确实根据一些道具(或数据)渲染了 li 标签。跨度>
  • 然后使用getInitialState()中的props数据计算最大值,并将其放入状态。似乎不需要等待组件被挂载。
  • 异步数据呢?
  • 不要将派生值设置为状态。在你的渲染函数中使用const numLi = liList.length

标签: reactjs


【解决方案1】:

componentDidMount 中调用setState 不是反模式。事实上,ReactJS 在their documentation 中提供了一个这样的例子:

您应该在 componentDidMount 生命周期方法中使用 AJAX 调用填充数据。这样您就可以在检索数据时使用 setState 更新您的组件。

Example From Doc

componentDidMount() {
    fetch("https://api.example.com/items")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result.items
          });
        },
        // Note: it's important to handle errors here
        // instead of a catch() block so that we don't swallow
        // exceptions from actual bugs in components.
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }

【讨论】:

  • setState 在这里的回调函数中完成 - 这有点像different scenario
  • 我不确定它是否是反模式。 current documentation 提到在 componentDidMount 中设置状态会触发重新渲染,但没有提到这是不好的做法。
  • 所以,只是为了澄清其他偶然发现这个问题和答案的人,生命周期函数isMounted 已被弃用,使用它来设置组件状态被认为是一种反模式。通过componentDidMount 设置状态不被视为反模式。
  • 只是想添加一个注释,有一个Github discussion on this,如果您正在做一些服务器端渲染或请求数据,建议您在componentDidMount中调用setState。但是,通常不推荐这样做的原因是它可以触发双重渲染(参见eslint rule no-did-mount-set-state
  • @lux 我不记得这里的细节,但我想我只是指出这里的机制有点不同 - 最初的问题似乎不需要异步调用来设置想要的状态。我并不是说您的代码无效:)
【解决方案2】:

根据 React 文档,从 componentDidMount() 函数中调用 setState() 是完全可以的。

这将导致render()被调用两次,这比只调用一次效率低,但除此之外它完全没问题。

您可以在此处找到文档:

https://reactjs.org/docs/react-component.html#componentdidmount

这是文档的摘录:

您可以立即在 componentDidMount() 中调用 setState()。它会 触发额外的渲染,但它会在浏览器之前发生 更新屏幕。这保证了即使 render() 将 在这种情况下被调用两次,用户不会看到中间 状态。谨慎使用此模式,因为它通常会导致 性能问题...

【讨论】:

    【解决方案3】:

    linter 抱怨在componentDidMountcomponentDidUpdate 中使用setState({..}) 的唯一原因是,当组件渲染时,setState 会立即导致组件重新渲染。 但最重要的是要注意:在这些组件的生命周期中使用它并不是 React 中的反模式。

    请看一下这个issue。你会更多地了解这个话题。 感谢您阅读我的回答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-25
      • 2018-11-27
      相关资源
      最近更新 更多