【问题标题】:How to see the effect of componentDidMount() in React Native如何在 React Native 中查看 componentDidMount() 的效果
【发布时间】:2018-02-07 07:06:35
【问题描述】:

为了实现componentDidMount()的效果,我写了如下代码段:

class Blink extends Component {
  constructor(props) {
    super(props);

    this.state = {output: 'c'};
  }
  componentWillMount() {
    this.state.output += 'w';
  }
  render() {
    this.state.output += 'r';
    let display = this.state.output;
     return (
       <Text>{display}</Text>
     );
  }
  componentDidMount() {
    this.state.output += 'd';
    this.setState();
  }
}

export default class BlinkApp extends Component {
  render() {
    return (
      <View>
        <Blink text='I love to blink' />
        <Blink text='Yes blinking is so great' />
        <Blink text='Why did they ever take this out of HTML' />
        <Blink text='Look at me look at me look at me' />
      </View>
    );
  }

我预计会看到四行'cwrdr',原因有二:

  1. 执行顺序:constructor(props)->componentWillMount()->render()->componentDidMount()

  2. componentDidMount() 中调用的 setState() 将再次调用 render()。

请分享您对我的代码和推理的想法。非常感谢。

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    你犯了改变状态的错误,使用这行this.state.output += 'd';。这样一来,React 就不再知道什么时候该触发应用程序的重新渲染了。

    相反,您想使用setState({output : this.state.output + 'd'})。这会为您的状态分配一个新对象,并且渲染将按预期工作。

    此外,您应该从 componentWillMount 生命周期中删除 this.state.output += 'w';。您应该在此生命周期方法中执行任何状态更改操作,因为它不会触发重新渲染。

    componentWillMount() 在安装发生之前立即调用。它在 render() 之前调用,因此在此方法中设置状态不会触发重新渲染。避免在此方法中引入任何副作用或订阅。

    【讨论】:

    • You should NOT do any state-changing operations in this lifecycle method, as it will trigger an endless re-render loop and crash your application. 这是不正确的
    • @DragoşPaulMarinescu 感谢您的回答。这启发了我做一些小实验。我尝试在每个生命周期方法中将 this.state.output 语句替换为 setState 调用,并观察到以下发现:(1)这样的更改并没有影响 componentWillMount();两者都有效; (2) 我们不能在 render() 中使用 setState(),这会在超出最大更新深度时产生错误;但是, this.state.output 工作得很好; (3) 在componentDidMount() 中,正如你所说,this.state.output 不正确,只有this.setState() 有效,所以我看到了'cwrdr'。
    【解决方案2】:

    首先你不应该直接改变状态。根据文档:

    永远不要直接改变 this.state,因为之后调用 setState() 可能 替换您所做的突变。把 this.state 当作是 不可变。

    其次:您在渲染中看不到'cwrdr' 的原因是this.setState() 从v16 开始不再触发重新渲染。来自blog post

    使用 null 调用 setState 不再触发更新。这允许 如果要重新渲染,您可以在更新程序功能中决定。

    最后:不要在componentWillMount 中同步setState,而是在构造函数中这样做。

    componentWillMount() 在安装发生之前立即调用。它 在render() 之前调用,因此在此方法中设置状态将 不会触发重新渲染。避免引入任何副作用或 此方法中的订阅。

    还要尽可能避免使用 componentWillMount,因为从 v16.3.0 开始,react 建议重命名它并从 v17 开始弃用它。检查this answer on where to place async Requests

    【讨论】:

    • this.setState() no longer triggers a re-render from v16 onwards。这不是真的。如果您使用null 调用它,它不再触发重新渲染。那是不同的。
    • @DragoşPaulMarinescu,请检查此代码框codesandbox.io/s/01l8nkv83p
    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    相关资源
    最近更新 更多