在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
当前回答
本·卡普的答案对我来说似乎是唯一有效的答案。
但由于我们使用的是函数式方法,另一种方法可以受益于闭包和HoC:
const InjectWillmount = function(Node, willMountCallback) {
let isCalled = true;
return function() {
if (isCalled) {
willMountCallback();
isCalled = false;
}
return Node;
};
};
然后使用它:
const YourNewComponent = InjectWillmount(<YourComponent />, () => {
console.log("your pre-mount logic here");
});
其他回答
对你最初的问题的简短回答,componentWillMount如何与React Hooks一起使用:
componentWillMount已弃用,被认为是遗留的。反应推荐:
通常,我们建议使用构造函数()来初始化状态。
现在,在Hook FAQ中,你会发现函数组件的类构造函数的等价是:
构造函数:函数组件不需要构造函数。你可以在useState调用中初始化这个状态。如果计算初始状态的开销很大,您可以将一个函数传递给useState。
componentWillMount的用法示例如下所示:
const MyComp = () => {
const [state, setState] = useState(42) // set initial value directly in useState
const [state2, setState2] = useState(createInitVal) // call complex computation
return <div>{state},{state2}</div>
};
const createInitVal = () => { /* ... complex computation or other logic */ return 42; };
本·卡普的答案对我来说似乎是唯一有效的答案。
但由于我们使用的是函数式方法,另一种方法可以受益于闭包和HoC:
const InjectWillmount = function(Node, willMountCallback) {
let isCalled = true;
return function() {
if (isCalled) {
willMountCallback();
isCalled = false;
}
return Node;
};
};
然后使用它:
const YourNewComponent = InjectWillmount(<YourComponent />, () => {
console.log("your pre-mount logic here");
});
你不能在钩子中使用任何现有的生命周期方法(componentDidMount, componentDidUpdate, componentWillUnmount等)。它们只能在类组件中使用。而Hooks只能用于功能组件。下面这句话来自React文档:
如果你熟悉React类的生命周期方法,你可以把useEffect Hook看作componentDidMount、componentDidUpdate和componentWillUnmount的组合。
建议是,可以在功能组件中从类组件中模拟这些生命周期方法。
componentDidMount中的代码在组件挂载时运行一次。useEffect钩子等价于此行为是
useEffect(() => {
// Your code here
}, []);
注意这里的第二个参数(空数组)。这将只运行一次。
如果没有第二个参数,useEffect钩子将在组件的每次渲染时被调用,这可能是危险的。
useEffect(() => {
// Your code here
});
componentWillUnmount用于清理(比如删除事件监听器,取消定时器等)。假设您正在componentDidMount中添加一个事件侦听器,并在componentWillUnmount中删除它,如下所示。
componentDidMount() {
window.addEventListener('mousemove', () => {})
}
componentWillUnmount() {
window.removeEventListener('mousemove', () => {})
}
与上述代码等价的钩子如下所示
useEffect(() => {
window.addEventListener('mousemove', () => {});
// returned function will be called on component unmount
return () => {
window.removeEventListener('mousemove', () => {})
}
}, [])
考虑到
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钩子
So for React hooks, I think declaring your logic before the return statement can work. You should have a state that is set to true by default. In my case, I called the state componentWillMount. Then a conditional to run a block of code when this state is true (the block of code contains the logic you want executed in your componentWillMount), the last statement in this block should be resetting the componentWillMountState to false (This step is important because if it is not done, infinite rendering will occur) Example
// do your imports here
const App = () => {
useEffect(() => {
console.log('component did mount')
}, [])
const [count, setCount] = useState(0);
const [componentWillMount, setComponentWillMount] = useState(true);
if (componentWillMount) {
console.log('component will mount')
// the logic you want in the componentWillMount lifecycle
setComponentWillMount(false)
}
return (
<div>
<div>
<button onClick={() => setCount(count + 1)}>
press me
</button>
<p>
{count}
</p>
</div>
</div>
)
}