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

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

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


当前回答

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

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

其他回答

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

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

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

这可能不是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

对你最初的问题的简短回答,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; };

你不能在钩子中使用任何现有的生命周期方法(componentDidMount, componentDidUpdate, componentWillUnmount等)。它们只能在类组件中使用。而Hooks只能用于功能组件。下面这句话来自React文档:

如果你熟悉React类的生命周期方法,你可以把useEffect Hook看作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', () => {})
  }
}, [])

对于大多数人来说,这可能很清楚,但请记住,在函数组件体内调用的函数充当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