ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

React 函数组件生命周期

2022-09-13 09:05:31  阅读:405  来源: 互联网

标签:生命周期 函数 渲染 React 计数器 组件 构造函数


React 函数组件生命周期

生命周期方法是在组件的不同阶段执行的自定义功能。当组件被创建并插入 DOM 时,有一些方法可用( 安装 )、组件更新时以及组件从 DOM 中卸载或移除时。

以下是类组件的生命周期方法:

我们想知道如何在组件函数中实现这些方法。

构造函数()

在基于类的组件中,我们经常看到使用构造函数来初始化状态的代码,如下所示:

 类应用扩展组件{  
 构造函数(道具){  
 超级(道具);  
 这个.state = {  
 计数器:0  
 };  
 } 渲染 = () => {  
 返回 (  
 <button  
 onClick={() =>  
 this.setState(prevState => {  
 返回 { 计数器:prevState.counter + 1 };  
 })  
 }  
 >  
 增量:{this.state.counter}  
 </button>  
 );  
 };  
 }

但完全相同的事情可以这样完成:

 类应用扩展组件{  
 状态={计数器:0}; 渲染 = () => {  
 返回 (  
 <button  
 onClick={() =>  
 this.setState(prevState => {  
 返回 { 计数器:prevState.counter + 1 };  
 })  
 }  
 >  
 增量:{this.state.counter}  
 </button>  
 );  
 };  
 }

如您所见,您可以直接在类下声明初始状态。
当您查看 Hooks 的常见问题解答时 reactjs.org ,它有一个部分专门回答,“生命周期方法如何对应Hooks?”本节的第一个要点说:

_构造函数_ : 函数组件不 ** 需要** (重点:我的)一个构造函数。您可以在 _使用状态_ 称呼。如果计算初始状态很昂贵,您可以将函数传递给 _使用状态_ .

当我想到构造函数时,我会想到这些特征。

  1. 运行的代码 在此组件的生命周期中的任何其他内容之前 .
  2. 运行一次的代码, 而且只有一次 , 用于该组件的整个生命周期。

因此,尽管 Hooks 团队做出了大胆的断言,但事实是 当我 需要一个构造函数(或一些等价物)。

自定义挂钩救援

我们可以 进口 将“类构造器”功能添加到任何需要的功能组件中。代码如下所示:

 const useConstructor(callBack = () => {}) => {  
 常量 [hasBeenCalled, setHasBeenCalled] = useState(false);  
 if (hasBeenCalled) 返回;  
 打回来();  
 setHasBeenCalled(true);  
 } 常量应用 = () => {  
 使用构造器(()=> {  
 控制台日志(  
 “这只会发生一次。  
 它发生在初始渲染之前。”  
 );  
 });  
 const [计数器,setCounter] = useState(0); 返回 (  
 <>  
 <div>计数器:{计数器}</div>  
 <div style={{ marginTop: 20 }}>  
 <button onClick={() =>设置计数器(计数器 + 1)}></button>  
 增量  
 </button>  
 </div>  
 </>  
 );  
 };

如果您将该逻辑放在函数声明的最顶部,则它实际上是一个“构造函数”,无论出于何种意图和目的。

GetDerivedStateFromProps()

虽然你可能 不需要它 , 在极少数情况下您会这样做(例如实施 <Transition> 组件),您可以在渲染期间更新状态。 React 将在退出第一次渲染后立即以更新的状态重新运行组件,因此它不会很昂贵。

在这里,我们存储之前的值 prop 在状态变量中,以便我们可以比较:

 函数滚动视图({row}){  
 const [isScrollingDown, setIsScrollingDown] = useState(false);  
 常量 [prevRow, setPrevRow] = useState(null);如果(行!== prevRow){  
 // 自上次渲染后行已更改。更新 isScrollingDown。  
 setIsScrollingDown(prevRow !== null && row > prevRow);  
 setPrevRow(行);  
 } return `向下滚动:${isScrollingDown}`;  
 }

渲染期间的更新正是 getDerivedStateFromProps 在概念上一直是这样的。

使成为()

在基于类的组件中,我们有一个舒适(恕我直言) 使成为() 功能。如果某个特定的逻辑应该 不是 运行 每一个 重新渲染,这个过程非常简单:只是不要把那个逻辑 使成为() 功能。

但是功能组件没有提供开箱即用的等效项。这是函数组件体本身。那里 没有 使成为() 功能。只有一个 返回 .这 返回 (以及函数体中的所有其余代码)被调用 每次调用此函数 .

 常量应用 = () => {  
 const [计数器,setCounter] = useState(0); _console.log("每次渲染都会发生这种情况。");_ 返回 (  
 <>  
 <div>计数器:{计数器}</div>  
 <div style={{ marginTop: 20 }}>  
 <button onClick={() =>setCounter(counter + 1)}>增量</button>  
 </div>  
 </>  
 );  
 };

ComponentWillMount()、ComponentDidMount()、ComponentDidUpdate()、ComponentWillUnmount()

使用效果 hook 可以表达这些的所有组合。了解我们如何使用 组件WillMount 对于功能组件,首先我们需要看看组件如何使用 useEffect 管理挂载。

 常量应用 = () => {  
 使用效果(()=> {  
 控制台日志(  
 “这只发生一次。它发生在初始渲染之后。”  
 );  
 }, []);  
 };

如果在 useEffect 函数中添加返回函数,它会在组件从 DOM 卸载时触发。这看起来像:

 常量应用 = () => {  
 使用效果(()=> {  
 返回 () => {  
 控制台日志(  
 “这只会发生一次。  
 这里的任何东西都会在组件 UNMOUNT 上触发。”  
 );  
 }  
 }, []);  
 };

结合两种解决方案:

这意味着您可以在同一个 useEffect 函数调用中使用 componentDidMount 和 componentWillMount。显着减少管理这两个生命周期事件所需的代码量。这意味着您可以轻松地在功能组件中使用 componentDidMount 和 componentWillMount。

像这样:

 常量应用 = () => {  
 使用效果(()=> {  
 控制台日志(  
 “这只会发生一次。  
 这里的任何东西都会在组件 MOUNT 上触发。”  
 );  
 返回 () => {  
 控制台日志(  
 “这只会发生一次。  
 这里的任何东西都会在组件 UNMOUNT 上触发。”  
 );  
 }  
 }, []);  
 };

componentWillMount 和 componentWillUnmount,非常相似!

应该组件更新()

您可以使用 反应备忘录 浅比较它的道具:

 const Button = React.memo((props) => {  
 // 你的组件  
 });

它不是 Hook,因为它不像 Hook 那样组成。 反应备忘录 等价于 PureComponent,但它只比较 props。 (您还可以添加第二个参数来指定一个自定义比较函数,该函数采用新旧道具。如果它返回 true,则跳过更新。)

反应备忘录 不比较状态,因为没有要比较的单个状态对象。但是你也可以让孩子变得纯洁,甚至优化个别孩子 使用备忘录 .

getSnapshotBeforeUpdate(),

componentDidCatch() 和 getDerivedStateFromError()

这些方法还没有 Hook 等价物,但很快就会添加。

结论

React 组件生命周期一开始可能会令人生畏,并且可能会有些混乱,但希望这能让您更好地理解函数组件中的这个概念。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/33146/35001308

标签:生命周期,函数,渲染,React,计数器,组件,构造函数
来源: https://www.cnblogs.com/amboke/p/16688001.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有