构造函数与组件WillMount; componentWillMount 能做啥而构造函数不能?

Posted

技术标签:

【中文标题】构造函数与组件WillMount; componentWillMount 能做啥而构造函数不能?【英文标题】:constructor vs componentWillMount; what a componentWillMount can do that a constructor cannot?构造函数与组件WillMount; componentWillMount 能做什么而构造函数不能? 【发布时间】:2017-04-11 05:07:08 【问题描述】:

据我所知,componentWillMount 唯一能做而constructor 不能做的就是打电话给setState

componentWillMount() 
    setState( isLoaded: false );

由于我们还没有调用rendercomponentWillMount 中的setState 将在我们进入第一个render() 传递之前准备状态对象。这与constructor 所做的基本相同:

constructor(props) 
    super(props);
    this.state =  isLoaded: false ;


但我看到另一个用例componentWillMount 很有用(在服务器端)。

让我们考虑一些异步的东西:

componentWillMount() 
    myAsyncMethod(params, (result) => 
        this.setState( data: result );
    )

这里我们不能使用constructor 作为对this.state 的赋值不会触发render()

componentWillMount 中的setState 怎么样?根据React docs:

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

所以,在这里我认为 React 将使用新的状态值进行第一次渲染并避免重新渲染。

问题 1:这是否意味着,在 componentWillMount 内部,如果我们在异步方法的回调(可以是 Promise 回调)中调用 setState,React 会阻止初始渲染 直到回调被执行?

客户端上进行此设置(是的,我在服务器端渲染中看到了该用例),如果我假设上述情况属实,那么在我的异步方法完成之前我将看不到任何东西。

我是否遗漏了任何概念?

问题 2:我可以仅使用 componentWillMount 而不是使用 constructorcomponentDidMount 实现的任何其他用例吗?

【问题讨论】:

问题 1:这是否意味着,在 componentWillMount 内部,如果我们在异步方法的回调(可以是 Promise 回调)中调用 setState,React 会阻塞初始渲染,直到回调被执行?" 肯定不是——它怎么知道?React 很强大,但并不神奇。 我想知道我的第一个问题是否完全有效,否则我想知道componentWIllMount 的真实用例是什么。很抱歉在一个问题中问了两个问题。我不想在另一个问题中重复我所有的研究故事。 :) 【参考方案1】:

这是否意味着,在 componentWillMount 内部,如果我们在一个 async 方法的回调(可以是 promise 回调),React 块 执行回调之前的初始渲染?

不,请参阅here。

以下代码不会阻止渲染(请记住,无论如何调用 setState 都是一种反模式)

componentWillMount: function() 
     new Promise((resolve, reject) => 
        setTimeout(()=> 
            resolve();
        , 2000)
     ).then(() => this.setState( promiseResult: 'World' ));
  ,

问题 2:我可以使用哪些其他用例来实现 仅 componentWillMount,但不使用构造函数和 componentDidMount?

不,对于 ES6 类,您可以丢弃 componentWillMount。只有使用React.createClass(... )时才需要

编辑:显然,我错了。感谢@Swapnil 指出这一点。这是discussion。

如果constructor 中存在修改另一个组件中的状态的副作用,React 会抛出警告,因为它假定constructor 本身中的setState 可能在render() 期间被调用。因此,constructor 没有副作用。

如果您在componentWillMount 中执行此操作,则不会出现任何错误。另一方面,来自 facebook 的人也反对 componentWillMount 中的副作用。因此,如果您没有任何副作用,您可以使用constructor 而不是componentWillMount。对于副作用,建议使用componentDidMount 而不是componentWillMount。 无论哪种方式,您都不需要componentWillMount

【讨论】:

对于 ES6,如果我使用 Redux 并希望在初始加载时调度一个动作,建议在 componentWillMount 而不是构造函数中调度动作。 It says that over here 还有一件事。我的名字是 Swapnil 而不是 Swapnii :p 我需要眼镜;-) @leo,在你分享的小提琴中,我在render() 中放了一个日志。我观察到的是,React 在第一次渲染时会渲染一个“Hello”。然后在 2s 后发生超时,从componentWillMount 调用setState。 React 更新了 DOM 上的新状态值,尽管它没有重新渲染!!这对我来说很神秘!它是如何在不重新渲染的情况下更新 DOM 的? (我很确定,我在这里遗漏了一些关于 React 的内容)。 对不起,是我的眼睛出卖了我!!你是对的,是的,它重新渲染。哦,现在我明白了,setState 不是从 componentWillMount 闭包中调用的。它是从另一个作用域调用的,即回调函数的 env;从而触发了渲染。所以反应文档是正确的,componentWillMount 内部的setState 不会触发重新渲染:)

以上是关于构造函数与组件WillMount; componentWillMount 能做啥而构造函数不能?的主要内容,如果未能解决你的问题,请参考以下文章

注入与子组件同类型的父组件

我应该在其构造函数中还是在 app.component 的 ngOnInit 方法中初始化 Angular 服务?

扩展类时的构造函数注入

无法通过构造函数将组件注入组件?

Angular 组件构造函数被调用两次

使用构造函数参数测试 Angular 2 组件