【问题标题】:React lifecycle methods not trigger, is there some hack behind lifecycle methods?React 生命周期方法没有触发,生命周期方法背后是否有一些技巧?
【发布时间】:2020-06-16 04:13:22
【问题描述】:

今天我发现了一些出乎我意料的东西。这不会发生在 Angular 或其他 JS 库/框架中。但是今天当 React 生命周期方法没有被触发时,我感到震惊。它背后是否有一些黑客行为。让我们看看代码。

我有一个组件A

import React, { Component } from 'react'

class A extends Component {
  componentDidMount() {
    console.log('component mount', this.props.name);
  }

  render() {
    return (
      <>
        Hello - {this.props.name}
      </>
    )
  }
}

export default A;

我在 App 组件中使用某些条件对该组件进行了两次初始化:

import React, { Component } from 'react';
import { render } from 'react-dom';
import A from './A';
import './style.css';

class App extends Component {
  constructor() {
    super();
    this.state = {
      isShow: true
    };

    this.setIsShow = this.setIsShow.bind(this);
  }

  setIsShow() {
    this.setState(() => {
      return {isShow: !this.state.isShow};
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.setIsShow}>Show A1</button>
        <button onClick={this.setIsShow}>Show A2</button>
        <br />
        <br />
        {this.state.isShow ? <A name="A1" /> 
        :
        <A name="A2" />
        }
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

现在,预期的行为是什么?当我点击按钮时,name 道具值发生了变化。这是预期的,好吧。但是当组件重新初始化时没有调用生命周期方法:(。componentDidMount只触发一次。

现在在 A 组件选择器中添加 key 属性,您将看到每次 A 时都会调用 componentDidMount组件已重新初始化。

{
 this.state.isShow ? <A name="A1" key="1" /> 
 :
 <A name="A2" key="2" />
}

这是预期的行为。但问题是为什么不能没有 key 属性。

结帐在线演示:https://stackblitz.com/edit/problem-react-lifecycle

【问题讨论】:

  • 使用getDerivedStateFromProps方法获取修改后的props
  • 问题不是如何解决这个问题,问题是它破坏了组件定义和它的生命周期:)
  • 除了它不会破坏生命周期,因为它只是没有卸载和重新安装组件。

标签: javascript reactjs angular react-native react-lifecycle


【解决方案1】:

这里发生的是 react 正在为您优化渲染。使用更新的 prop 渲染相同的组件与使用不同的 prop 卸载和重新安装。

生命周期事件运行良好,您只是看不到您的console.log,因为componentDidMount 仅在挂载时触发。如果您使用像 componentDidUpdate 这样的另一个生命周期事件,您会注意到它会在每次更改时触发。

componentDidUpdate() {
  console.log("component update", this.props.name);
}

See a live example here

当您没有指定键时,react 将在内部添加一个...如果组件相同,则将为该组件生成相同的键,这意味着它不会被卸载。基本上不需要承受卸载和重新安装的额外开销。

但是,为组件指定不同的键会强制卸载和重新安装,因为您已经告诉它应该将它们视为完全不同的组件

【讨论】:

    【解决方案2】:

    已编辑: 这是因为 React 正在优化以不重新渲染整个组件。添加另一个生命周期方法将在控制台中显示预期的输出

    componentDidUpdate() {
      console.log('component update', this.props.name);
    }
    

    【讨论】:

    • 多个状态更新发生在哪里,要批量处理?用this.setState(prevState =&gt; ({isShow: !prevState.isShow})); 测试,仍然可以复制。
    • @John Ruddell 是正确的,只需尝试将 componentDidUpdate 添加到您的 A.js 文件中,您就会看到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多