在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
当前回答
这是我如何使用useRef钩子模拟函数组件中的构造函数的方式:
function Component(props) {
const willMount = useRef(true);
if (willMount.current) {
console.log('This runs only once before rendering the component.');
willMount.current = false;
}
return (<h1>Meow world!</h1>);
}
下面是生命周期的例子:
function RenderLog(props) {
console.log('Render log: ' + props.children);
return (<>{props.children}</>);
}
function Component(props) {
console.log('Body');
const [count, setCount] = useState(0);
const willMount = useRef(true);
if (willMount.current) {
console.log('First time load (it runs only once)');
setCount(2);
willMount.current = false;
} else {
console.log('Repeated load');
}
useEffect(() => {
console.log('Component did mount (it runs only once)');
return () => console.log('Component will unmount');
}, []);
useEffect(() => {
console.log('Component did update');
});
useEffect(() => {
console.log('Component will receive props');
}, [count]);
return (
<>
<h1>{count}</h1>
<RenderLog>{count}</RenderLog>
</>
);
}
[Log] Body
[Log] First time load (it runs only once)
[Log] Body
[Log] Repeated load
[Log] Render log: 2
[Log] Component did mount (it runs only once)
[Log] Component did update
[Log] Component will receive props
当然,Class组件没有Body步骤,由于函数和类的概念不同,不可能进行1:1的模拟。
其他回答
只需要简单地在useEffect中添加一个空的依赖数组,它将作为componentDidMount工作。
useEffect(() => {
// Your code here
console.log("componentDidMount")
}, []);
对你最初的问题的简短回答,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; };
考虑到
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钩子
我们最近遇到了这个问题,因为我们需要在组件挂载时做一些事情,也就是我们需要更新全局状态。
所以我创建了这个钩子,不确定这个方法有多好,但到目前为止,只要我们少用它,只用于简单的任务,它就能工作。我可能不会将它用于网络请求和其他长时间运行的复杂任务。
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;
我写了一个自定义钩子,它将在第一次渲染之前运行一个函数。
useBeforeFirstRender.js
import { useState, useEffect } from 'react'
export default (fun) => {
const [hasRendered, setHasRendered] = useState(false)
useEffect(() => setHasRendered(true), [hasRendered])
if (!hasRendered) {
fun()
}
}
用法:
import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'
export default () => {
useBeforeFirstRender(() => {
console.log('Do stuff here')
})
return (
<div>
My component
</div>
)
}