在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
当前回答
钩子中的React生命周期方法
为了简单的视觉参考,请遵循此图像
正如您在上图中所看到的,对于ComponentWillUnmount,您必须这样做
useEffect(() => {
return () => {
console.log('componentWillUnmount');
};
}, []);
其他回答
useComponentWillMount钩
const useComponentWillMount = (cb) => {
const willMount = useRef(true)
if (willMount.current) cb()
willMount.current = false
}
当出现顺序问题(比如在另一个脚本之前运行)时,这个钩子可以作为一个保护程序。如果不是这样,请使用useComnponentDidMount,它更符合React钩子的范例。
useComponentDidMount钩
const useComponentDidMount = cb => useEffect(cb, []);
如果你知道你的效果应该只运行一次在开始使用这个解决方案。它只会在组件挂载后运行一次。
useEffect范式
类组件具有生命周期方法,这些方法定义为组件时间轴上的点。钩子不遵循这种范式。相反,效果应该由内容构成。
function Post({postID}){
const [post, setPost] = useState({})
useEffect(()=>{
fetchPosts(postID).then(
(postObject) => setPost(postObject)
)
}, [postID])
...
}
在上面的例子中,效果处理的是获取文章的内容。而不是一个特定的时间点,它有一个它所依赖的值- postID。每次postID得到一个新值(包括初始化),它都会重新运行。
组件将挂载讨论
在类组件中,componentWillMount被认为是遗留的(源1,源2)。它是遗留的,因为它可能运行不止一次,而且还有另一种选择——使用构造函数。这些考虑因素与功能组件无关。
对你最初的问题的简短回答,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; };
这是我如何使用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的模拟。
componentWillMount已弃用(正如在其他评论中提到的),原因是我认为它很容易被一个简单的HOC处理。
const withComponentWillMount = (WrappedComponent, handler) => {
return (props) => {
return handler(props) ? <WrappedComponent {...props} /> : null;
}
}
我通常在我的项目中实现这个解决方案。使用此HOC,如果处理程序返回false,则组件内部不运行任何内容,包括钩子。
本·卡普的答案对我来说似乎是唯一有效的答案。
但由于我们使用的是函数式方法,另一种方法可以受益于闭包和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");
});