在React的官方文档中提到了-

如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。

我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?


当前回答

componentWillMount已弃用(正如在其他评论中提到的),原因是我认为它很容易被一个简单的HOC处理。

const withComponentWillMount = (WrappedComponent, handler) => {
  return (props) => {
    return handler(props) ? <WrappedComponent {...props} /> : null;
  }
}

我通常在我的项目中实现这个解决方案。使用此HOC,如果处理程序返回false,则组件内部不运行任何内容,包括钩子。

其他回答

钩子中的React生命周期方法

为了简单的视觉参考,请遵循此图像

正如您在上图中所看到的,对于ComponentWillUnmount,您必须这样做

 useEffect(() => {
    return () => {
        console.log('componentWillUnmount');
    };
   }, []);

只需要简单地在useEffect中添加一个空的依赖数组,它将作为componentDidMount工作。

useEffect(() => {
  // Your code here
  console.log("componentDidMount")
}, []);

这可能不是componentWillMount方法的确切替代方法,但这里有一个方法可以用来实现同样的目标,但要使用useEffect:

首先初始化检索数据的对象为空值,并定义useEffect方法:

const [details, setDetails] = useState("")

  useEffect(() => {
    retrieveData(); 
  }, []);

const retrieveData = () => {       
       getData()                  // get data from the server 
      .then(response => {
        console.log(response.data);
        setDetails(response.data)
      })
      .catch(e => {
        console.log(e);
      })
  }

在JSX中,我们返回一个三元操作符

*return(
  <div>
    { 
   details ? (
   <div class="">
   <p>add Your Jsx Here</p>
</div>
): (
  <div>
<h4>Content is still Loading.....</h4>
</div>
)
}
  </div>
)*

这将确保在对象'details'中有数据之前,terenary操作符的第二部分会被加载,该操作符会触发useEffect方法,该方法导致在'details'对象中设置从服务器接收到的数据,从而呈现主JSX

根据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

我们最近遇到了这个问题,因为我们需要在组件挂载时做一些事情,也就是我们需要更新全局状态。

所以我创建了这个钩子,不确定这个方法有多好,但到目前为止,只要我们少用它,只用于简单的任务,它就能工作。我可能不会将它用于网络请求和其他长时间运行的复杂任务。

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;