使用 Hook 实现 React 组件生命周期
在上一篇文章中,我解释了如何将类组件转换为函数组件,以便我们能够利用钩子。
文章链接如下:
在这篇文章中,我将帮助您了解如何使用带有反应钩子的组件生命周期来获得相同的输出。
我将介绍以下生命周期方法:
componentWillMount
componentDidMount
componentDidUpdate
shouldComponentUpdate
componentWillUnmount
在开始之前,让我们先了解一下以下钩子:
useState
useEffect
### useStateuseState
返回一个状态值和一个用于更新它的函数。#### 语法:### useEffect 使用功能组件,我们不允许在组件主体内部产生诸如突变、计时器、突变或任何其他副作用之类的副作用。
所以,这里我们在渲染完成后useEffect
运行了特效。默认情况下,特效会在每次渲染后运行,但有一些方法可以控制它,我们将在文章后面讨论。
句法:
有关钩子或 React 提供的任何其他钩子的更多详细信息,请查看官方文档。
因此,让我们从组件生命周期开始,并尝试了解如何用钩子替换它。
专业提示:请勿在任何代码块内使用钩子。它必须位于功能组件的顶层层次结构中。
让我们看一个小型应用程序的运行示例。它使用了基于 React 类的组件和生命周期。在文章末尾,您可以查看使用函数式组件创建的相同应用程序,其生命周期执行方式也与 React 类似。
让我们开始吧。
组件将要挂载
当我们将任何类组件转换为函数式组件时,我们可以在定义状态(如果有)之后useState
,或在代码到达渲染(jsx)部分之前编写代码来实现componentWillMount
行为。众所周知,代码的执行是自上而下的。
组件挂载
正如之前解释的那样useEffect
,我们可以传递第二个可选参数来实现该componentDidMount
行为。我们来看看下面的代码片段。
React.useEffect(()=>{
console.log('Robot: componentDidMount');
// ...code goes here...
fetchData();
}, []);
在上面的代码中,我们在第 5 行将[]
空数组作为第二个参数。为什么?🤔
因为提供的第二个参数仅在检测到任何提供的条目发生变化时才有助于响应并调用效果。此数组是我们作为第一个参数传递的函数的依赖项useEffect
。
在这种情况下,它是空白的,这意味着它永远不会检测到任何变化,所以它只会调用一次。这难道不就是吗componentDidMount
?只调用一次,对吧?
请注意,如果没有传入第二个参数
useEffect
,它将始终在渲染之后执行。
组件更新
假设我们需要在组件的任何 props 发生变化时再次调用 api,那么组件更新后,我们在这里执行此操作。我们可以使用 来实现useEffect
。不过,这次我们需要将一个条目传递给第二个参数。
React.useEffect(() => {
console.log('Robot: componentWillUpdate');
// code goes here
fetchData();
}, [props.selectedRobotId]);
这次,我们selectedRobotId
在数组中传递了一个 prop。因此,每当这个 prop 发生变化时,效果就会运行,我们就会得到更新后的组件。
应该组件更新
这个有点棘手,但让我来帮你理解一下。众所周知,这个生命周期方法可以帮助我们自行控制组件的渲染。以下是一个例子:
shouldComponentUpdate(nextProps, nextState) {
console.log("Robot: shouldComponentUpdate");
return (
nextProps.selectedRobotId !== this.props.selectedRobotId ||
nextState.loadedRobot.id !== this.state.loadedRobot.id ||
nextState.isLoading !== this.state.isLoading
);
}
但是,在函数式组件中,我们无法以这种方式使用 React 组件的生命周期方法。那么,如何实现同样的效果呢?
嗯,在 React 中,我们有一个叫做 的东西React.memo
。我们可以用它来包装组件,如下所示:
export default React.memo(Robot);
这看起来可以作为……的替代方案吗shouldComponentUpdate
?不……
好的,事情是这样的。接受第二个参数(一个函数),该参数提供对和 的React.memo
访问。这可以帮助我们实现与 相同的目的。nextProps
prevProps
shouldComponentUpdate
export default React.memo(Robot, (prevProps, nextProps) => {
console.log('Robot: shouldComponentUpdate');
return nextProps.selectedRobotId === prevProps.selectedRobotId;
});
这里有一点需要注意。这与 的作用相反。如果不想重新渲染,
shouldComponentUpdate
则返回true 。如果希望渲染,则返回false 。
React 很好地处理了这个问题,所以只有当你不想因为任何 props 更改而重新渲染时,才需要第二个函数。否则,就让 React 帮你处理吧。:)
组件将卸载
记得,在 的解释中useEffect
,我提到过 内部有一个可选的返回函数useEffect
。这个返回函数的作用是清理。
React.useEffect(() => {
console.log('Robot: componentDidUpdate');
//...code goes here
fetchData();
return () => {
console.log('cleaning up...');
}
}, [props.selectedRobotId])
上面的代码片段类似于componentDidUpdate
代码块,只是它现在有一个返回函数。因此,每当props.selectedRobotId
发生更改时,此效果都会运行,并且返回函数会在效果完成时调用,我们可以在其中进行清理。
但是,这与 的情况不同componentWillUnmount
。对吧?
好的,为了实现 ,componentWillUnmount
我们可以在代码中再添加一个useEffect
,并将第二个参数作为空数组([]
)传递。类似于 ,componentDidMount
但useEffect
这次 内部会有一个返回函数,它将像 一样工作componentWillUnmount
。
React.useEffect(() => {
//...code goes here
fetchData();
return () => {
console.log('cleaning up...');
}
}, [props.selectedRobotId]);
React.useEffect(() => {
//...code goes here
fetchData();
return () => {
console.log('Robot: componentWillUnmount');
}
}, []);
这为我们提供了两个层面的清理方法。一个是组件更新时,另一个是组件准备卸载时。
概括
在本文中,我们介绍了useState
和useEffect
。然后我们使用useEffect
和memo
实现了基于类的组件的组件生命周期方法。
乍一看,这可能有点令人困惑,但不用担心。这是相同应用程序(如上所示)的 Codepen,但使用了 React Hooks。
请查看代码并练习。如有任何问题或疑虑,欢迎分享或联系我。
学习愉快!
鏂囩珷鏉ユ簮锛�https://dev.to/elanandkumar/react-component-lifecycle-with-hook-6lo