在 React 的官方文档中它提到 -
如果您熟悉 React 类的生命周期方法,您可以将 useEffect Hook 视为 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。
我的问题是 - 我们如何componentWillMount()
在钩子中使用生命周期方法?
在 React 的官方文档中它提到 -
如果您熟悉 React 类的生命周期方法,您可以将 useEffect Hook 视为 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。
我的问题是 - 我们如何componentWillMount()
在钩子中使用生命周期方法?
你不能使用任何现有的生命周期方法(componentDidMount
,componentDidUpdate
,componentWillUnmount
在钩等)。它们只能在类组件中使用。使用 Hooks,您只能在功能组件中使用。下面这行来自 React 文档:
如果你熟悉阵营类生命周期方法,你能想到的
useEffect
钩。因为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', () => {})
}
}, [])
const useComponentWillMount = (cb) => {
const willMount = useRef(true)
if (willMount.current) cb()
willMount.current = false
}
当出现序列问题(例如在另一个脚本之前运行)时,这个钩子可以是一个保护程序。如果不是这种情况,请使用更符合 React hooks 范式的 useComnponentDidMount。
const useComponentDidMount = cb => useEffect(cb, []);
如果您知道您的效果应该在开始时只运行一次,请使用此解决方案。它只会在组件安装后运行一次。
类组件具有生命周期方法,这些方法被定义为组件时间线中的点。钩子不遵循这种范式。相反,效果应该由它们的内容来构建。
function Post({postID}){
const [post, setPost] = useState({})
useEffect(()=>{
fetchPosts(postID).then(
(postObject) => setPost(postObject)
)
}, [postID])
...
}
在上面的示例中,效果处理获取帖子的内容。它具有依赖于 - 的值,而不是某个时间点postID
。每次postID
获得新值(包括初始化)时,它都会重新运行。
在类组件中 componentWillMount 被认为是遗留的(源 1,源 2)。它是遗留的,因为它可能运行不止一次,还有一种替代方法 - 使用构造函数。这些注意事项与功能组件无关。
据 reactjs.org 称,将来将不支持 componentWillMount。 https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
无需使用 componentWillMount。
如果你想在组件挂载之前做一些事情,只需在constructor()中做。
如果要做网络请求,就不要在componentWillMount里做。这是因为这样做会导致意想不到的错误。
网络请求可以在 componentDidMount 中完成。
希望能帮助到你。
更新于 08/03/2019
你要求 componentWillMount 的原因可能是因为你想在渲染之前初始化状态。
只需在 useState 中执行即可。
const helloWorld=()=>{
const [value,setValue]=useState(0) //initialize your state here
return <p>{value}</p>
}
export default helloWorld;
或者您可能想在 componentWillMount 中运行一个函数,例如,如果您的原始代码如下所示:
componentWillMount(){
console.log('componentWillMount')
}
使用钩子,您需要做的就是删除生命周期方法:
const hookComponent=()=>{
console.log('componentWillMount')
return <p>you have transfered componeWillMount from class component into hook </p>
}
我只想在关于 useEffect 的第一个答案中添加一些内容。
useEffect(()=>{})
useEffect 在每次渲染上运行,它是 componentDidUpdate、componentDidMount 和 ComponentWillUnmount 的组合。
useEffect(()=>{},[])
如果我们在 useEffect 中添加一个空数组,它只会在组件安装时运行。这是因为 useEffect 会比较你传递给它的数组。所以它不一定是一个空数组。它可以是没有改变的数组。例如,它可以是 [1,2,3] 或 ['1,2']。useEffect 仍然只在组件安装时运行。
这取决于您是希望它只运行一次还是在每次渲染后运行。只要您知道自己在做什么,如果您忘记添加数组,这并不危险。
我为钩子创建了一个示例。请检查一下。
https://codesandbox.io/s/kw6xj153wr
21/08/2019 更新
自从我写了上面的答案已经有一段时间了。我认为你需要注意一些事情。当你使用
useEffect(()=>{},[])
当react比较您传递给数组 [] 的值时,它用于Object.is()
比较。如果你传递一个对象给它,比如
useEffect(()=>{},[{name:'Tom'}])
这与以下内容完全相同:
useEffect(()=>{})
每次都会重新渲染,因为当Object.is()
比较一个对象时,它比较的是它的引用,而不是值本身。这与{}==={} 返回false 的原因相同,因为它们的引用不同。如果您仍然想比较对象本身而不是引用,您可以执行以下操作:
useEffect(()=>{},[JSON.stringify({name:'Tom'})])
2021 年 7 月 9 日更新:
关于依赖项的一些更新:
一般来说,如果你使用一个函数或一个对象作为依赖,它总是会重新渲染。但是 react 已经为你提供了解决方案:useCallback 和 useMemo
useCallback 能够记住一个函数。useMemo 能够记住一个对象。
看这篇文章:
https://javascript.plainenglish.io/5-useeffect-infinite-loop-patterns-2dc9d45a253f
您可以破解 useMemo 钩子来模拟 componentWillMount 生命周期事件。做就是了:
const Component = () => {
useMemo(() => {
// componentWillMount events
},[]);
useEffect(() => {
// componentDidMount events
return () => {
// componentWillUnmount events
}
}, []);
};
您需要在与您的状态交互的任何内容之前保留 useMemo 挂钩。这不是它的意图,但它对我所有 componentWillMount 问题都有效。
这是有效的,因为 useMemo 不需要实际返回一个值,您实际上不必将它用作任何东西,但是因为它记住了一个基于依赖项的值,该依赖项只会运行一次(“[]”)并且它位于我们的组件之上当组件在其他任何事情之前安装时运行一次。