代码之家  ›  专栏  ›  技术社区  ›  Yangshun Tay

React钩子和组件生命周期等效物

  •  9
  • Yangshun Tay  · 技术社区  · 7 年前

    componentDidMount , componentDidUpdate ,及 componentWillUnmount 生命周期挂钩使用React挂钩,如 useEffect ?

    1 回复  |  直到 7 年前
        1
  •  58
  •   Yangshun Tay    7 年前

    componentDidMount

    将空数组作为第二个参数传递给 useEffect() 仅在装载时运行回调。

    function ComponentDidMount() {
      const [count, setCount] = React.useState(0);
      React.useEffect(() => {
        console.log('componentDidMount');
      }, []);
    
      return (
        <div>
          <p>componentDidMount: {count} times</p>
          <button
            onClick={() => {
              setCount(count + 1);
            }}
          >
            Click Me
          </button>
        </div>
      );
    }
    
    ReactDOM.render(
      <div>
        <ComponentDidMount />
      </div>,
      document.querySelector("#app")
    );
    <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
    
    <div id="app"></div>

    componentDidUpdate

    componentDidUpdate() useEffect 在每个渲染(包括第一个渲染)上运行。所以如果你想有一个严格的等价物 组件更新 useRef 确定组件是否已安装一次。如果你想更严格,使用 useLayoutEffect() ,但它是同步发射的。在大多数情况下, useffect() 应该足够了。

    answer is inspired by Tholle

    function ComponentDidUpdate() {
      const [count, setCount] = React.useState(0);
    
      const isFirstUpdate = React.useRef(true);
      React.useEffect(() => {
        if (isFirstUpdate.current) {
          isFirstUpdate.current = false;
          return;
        }
    
        console.log('componentDidUpdate');
      });
    
      return (
        <div>
          <p>componentDidUpdate: {count} times</p>
          <button
            onClick={() => {
              setCount(count + 1);
            }}
          >
            Click Me
          </button>
        </div>
      );
    }
    
    ReactDOM.render(
      <ComponentDidUpdate />,
      document.getElementById("app")
    );
    <脚本src=”https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js“></脚本>
    <脚本src=”https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react dom.development.js“></脚本>
    

    componentWillUnmount

    在useffect的callback参数中返回一个回调,在卸载之前将调用该回调。

    function ComponentWillUnmount() {
      function ComponentWillUnmountInner(props) {
        React.useEffect(() => {
          return () => {
            console.log('componentWillUnmount');
          };
        }, []);
    
        return (
          <div>
            <p>componentWillUnmount</p>
          </div>
        );
      }
      
      const [count, setCount] = React.useState(0);
    
      return (
        <div>
          {count % 2 === 0 ? (
            <ComponentWillUnmountInner count={count} />
          ) : (
            <p>No component</p>
          )}
          <button
            onClick={() => {
              setCount(count + 1);
            }}
          >
            Click Me
          </button>
        </div>
      );
    }
    
    ReactDOM.render(
      <div>
        <ComponentWillUnmount />
      </div>,
      document.querySelector("#app")
    );
    <脚本src=”https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js“></脚本>
    
    <div id=“应用程序”></部门>
        2
  •  14
  •   Edan Chetrit    7 年前

    从…起 React docs :

    将效果挂钩用作componentDidMount、componentDidUpdate和

    他们的意思是:

    组件安装 有点 useEffect(callback, [])

    组件更新 有点 useEffect(callback, [dep1, dep2, ...]) 如果其中一个DEP被更改,请在呈现后运行回调 .

    useEffect(callback)

    组件将卸载 是回调函数返回的函数类型:

    useEffect(() => { 
        /* some code */
        return () => { 
          /* some code to run when rerender or unmount */
        }
    )
    

    Dan Abramov 这是他父亲的措辞 blog

    虽然您可以使用这些挂钩,但它并不是完全等效的。不像 componentDidMount componentDidUpdate 捕获 组件安装 最初的道具和状态)。如果你想看到最新的东西,你可以把它写在一个参考中。但是通常有一种更简单的方法来构造代码,这样你就不必这么做了。 返回的函数,假定它是 componentWillUnmount 也不是完全等效的,因为每次组件重新渲染和卸载时,函数都会运行。

    Dan博客中的示例:

    function Counter() {
      const [count, setCount] = useState(0);
    
      useEffect(() => {
        setTimeout(() => {
          console.log(`You clicked ${count} times`);
        }, 3000);
      });
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
    

    enter image description here

    如果我们使用类实现:

    componentDidUpdate() {
      setTimeout(() => {
        console.log(`You clicked ${this.state.count} times`);
      }, 3000);
    }
    

    enter image description here

    this.state.count 总是指向 最新的

        3
  •  3
  •   lokender singh Felix Kling    5 年前

    为了简单的解释,我想展示一个视觉参考

    enter image description here

    正如我们在上图中所看到的那样-

    组件安装:

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

    组件更新:

    useEffect(() => {        
       console.log('componentWillUpdate- runs on every update');
    });
    
    useEffect(() => {        
       console.log('componentWillUpdate - runs if dependency value changes ');
    },[Dependencies]);
    

      useEffect(() => {
        return () => {
            console.log('componentWillUnmount');
        };
       }, []);
    
        4
  •  2
  •   Community Mohan Dere    6 年前

    下面是一个很好的总结 React Hooks FAQ

    constructor :函数组件不需要构造函数。您可以在中初始化状态 useState 使用状态

    getDerivedStateFromProps :计划更新 while rendering 相反

    shouldComponentUpdate :见React.memo below

    render :这是功能组件主体本身。

    componentDidMount componentDidUpdate , componentWillUnmount 字体 useEffect Hook可以表示这些的所有组合(包括 less common

    componentDidCatch getDerivedStateFromError 号码 这些方法的钩子等价物还没有出现,但它们很快就会被添加。


    componentDidMount

    useEffect(() => { /*effect code*/ }, []);
    

    [] 将使效果在装载时仅运行一次。通常你最好 specify your dependencies . 具有与相同的布局计时 组件安装 ,看看 useLayoutEffect

    componentWillUnmount

    useEffect(() => { /*effect code*/ ; return ()=> { /*cleanup code*/ } }, [deps]); 
    

    组件将卸载 对应于具有 cleanup .

    componentDidUpdate

    const mounted = useRef();
    useEffect(() => {
      if (!mounted.current) mounted.current = true;
      else {
        // ... on componentDidUpdate 
      }
    });
    

    组件更新 ,看看 (大多数情况下不需要)。另见 this post 有关详细信息,请参见 钩子等价物。