在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中返回一个函数,如上所述。
其他回答
对你最初的问题的简短回答,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; };
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>
)
}
对于大多数人来说,这可能很清楚,但请记住,在函数组件体内调用的函数充当beforeRender。这并没有回答在ComponentWillMount上运行代码的问题(在第一次渲染之前),但由于它是相关的,可能会帮助其他人,所以我把它留在这里。
const MyComponent = () => {
const [counter, setCounter] = useState(0)
useEffect(() => {
console.log('after render')
})
const iterate = () => {
setCounter(prevCounter => prevCounter+1)
}
const beforeRender = () => {
console.log('before render')
}
beforeRender()
return (
<div>
<div>{counter}</div>
<button onClick={iterate}>Re-render</button>
</div>
)
}
export default MyComponent
React组件是一个函数?所以只要让componentWillMount moment成为return语句之前的函数体。
function componentWillMountMomentIsHere() {
console.log('component will mount')
}
function AnyComponent(){
const [greeting, setGreeting] = useState('Hello')
componentWillMountMomentIsHere()
return <h1>{greeting}</h1>
}
根据reactjs.org的说法,componentWillMount在未来将不受支持。 https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
不需要使用componentWillMount。
如果你想在组件挂载之前执行一些操作,只需在构造函数()中执行即可。
如果你想做网络请求,不要在componentWillMount中做。这是因为这样做会导致意想不到的错误。
网络请求可以在componentDidMount中完成。
希望能有所帮助。
2019年8月3日更新
你请求componentWillMount的原因可能是因为你想在呈现之前初始化状态。
就在我们的地盘上做吧。
const helloWorld=()=>{
const [value,setValue]=useState(0) //initialize your state here
return <p>{value}</p>
}
export default helloWorld;
或者你想在componentWillMount中运行一个函数,例如,如果你的原始代码看起来像这样:
componentWillMount(){
console.log('componentWillMount')
}
使用hook,你所需要做的就是删除生命周期方法:
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仍然只在组件挂载时运行。
这取决于你是想让它只运行一次,还是在每次渲染后运行。如果您忘记添加数组,只要您知道自己在做什么,这并不危险。
我为hook创建了一个示例。请查看一下。
https://codesandbox.io/s/kw6xj153wr
2019年8月21日更新
我写上面的答案已经有一段时间了。有件事我觉得你需要注意。 当你使用
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