在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
当前回答
正如react文档中所述:
您可能会认为我们需要一个单独的效果来执行 清理。但是添加和删除订阅的代码非常紧凑 useEffect的设计是为了将它们放在一起。如果你的效果 返回一个函数,React会在清理的时候运行它:
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
所以我们唯一需要在钩子中使用componentWillUnmount的是在useEffect中返回一个函数,如上所述。
其他回答
简单地在React.useEffect()中放置一个依赖数组作为第二个参数。如果任何依赖项更新,钩子将导致运行并最终更新组件的副作用。
我们最近遇到了这个问题,因为我们需要在组件挂载时做一些事情,也就是我们需要更新全局状态。
所以我创建了这个钩子,不确定这个方法有多好,但到目前为止,只要我们少用它,只用于简单的任务,它就能工作。我可能不会将它用于网络请求和其他长时间运行的复杂任务。
import { useRef } from 'react';
function useComponentWillMount(callback: () => void) {
const hasMounted = useRef(false);
if (!hasMounted.current) {
(() => {
hasMounted.current = true;
callback();
})();
}
console.log(hasMounted.current);
return null;
}
export default useComponentWillMount;
正如react文档中所述:
您可能会认为我们需要一个单独的效果来执行 清理。但是添加和删除订阅的代码非常紧凑 useEffect的设计是为了将它们放在一起。如果你的效果 返回一个函数,React会在清理的时候运行它:
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
所以我们唯一需要在钩子中使用componentWillUnmount的是在useEffect中返回一个函数,如上所述。
考虑到
componentWillMount已弃用(1,2,3),建议的替换是在构造函数中执行代码 在函数组件的return语句之前执行的代码在呈现之前隐式运行 与挂载类组件大致相当的是函数组件的初始调用 目标是在UI更新之前执行一些代码一次
解决办法是
在函数组件的主体中只运行一次函数。这可以通过useState、useMemo或useEffect来实现,具体取决于用例所需的时间。
由于代码需要在将初始呈现提交给屏幕之前运行,这将取消useEffect的资格,因为“传递给useEffect的函数将在将呈现提交给屏幕之后运行。”4。
因为我们想要保证代码只运行一次,这就使useMemo失去了资格,因为“在未来,React可能会选择“忘记”一些以前记住的值,并在下一次渲染时重新计算它们”5。
useState支持惰性初始状态计算,保证在初始渲染期间只运行一次,这似乎是一个很好的工作候选人。
useState的示例:
const runOnceBeforeRender = () => {};
const Component = () => {
useState(runOnceBeforeRender);
return (<></>);
}
作为自定义钩子:
const runOnceBeforeRender = () => {};
const useOnInitialRender = (fn) => {
useState(fn);
}
const Component = () => {
useOnInitialRender(runOnceBeforeRender);
return (<></>);
};
runOnceBeforeRender函数可以选择返回一个在函数第一次呈现时立即可用的状态,不会触发重新呈现。
一个(可能不必要的)NPM包:useOnce钩子
componentWillMount已弃用(正如在其他评论中提到的),原因是我认为它很容易被一个简单的HOC处理。
const withComponentWillMount = (WrappedComponent, handler) => {
return (props) => {
return handler(props) ? <WrappedComponent {...props} /> : null;
}
}
我通常在我的项目中实现这个解决方案。使用此HOC,如果处理程序返回false,则组件内部不运行任何内容,包括钩子。