反应钩子 useEffect() 清理仅用于 componentWillUnmount? [英] react hooks useEffect() cleanup for only componentWillUnmount?

查看:41
本文介绍了反应钩子 useEffect() 清理仅用于 componentWillUnmount?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我解释一下这段代码的结果,以便轻松提出我的问题.

const ForExample = () =>{const [name, setName] = useState('');const [username, setUsername] = useState('');useEffect(() => {console.log('效果');控制台日志({名称,用户名});返回 () =>{console.log('清理完毕');控制台日志({名称,用户名});};}, [用户名]);const handleName = e =>{const { value } = e.target;设置名称(值);};const handleUsername = e =>{const { value } = e.target;设置用户名(值);};返回 (<div><div><input value={name} onChange={handleName}/><input value={username} onChange={handleUsername}/>

<div><div><span>{name}</span>

<div><span>{用户名}</span>

);};

ForExample 组件 挂载时,将记录效果".这与 componentDidMount() 相关.

每当我更改名称输入时,都会记录效果"和清理".反之亦然,自从我将 [username] 添加到 useEffect() 的第二个参数后,每当我更改用户名输入时,都不会记录任何消息.这与componentDidUpdate()

有关

最后,当 ForExample 组件 卸载时,将记录已清理".这与 componentWillUnmount() 相关.

我们都知道这一点.

总而言之,只要重新渲染组件(包括卸载),就会调用清理"

如果我想让这个组件只在卸载时记录清理",我只需要将 useEffect() 的第二个参数更改为 [].

但是如果我将 [username] 更改为 []ForExample 组件 不再实现 componentDidUpdate()> 用于名称输入.

我想要做的是,使组件同时支持 componentDidUpdate() 仅用于名称输入和 componentWillUnmount().(仅在卸载组件时记录已清理")

解决方案

由于清理不依赖于 username,您可以将清理放在单独的 useEffect 中给定一个空数组作为第二个参数.

示例

const { useState, useEffect } = React;const ForExample = () =>{const [name, setName] = useState("");const [username, setUsername] = useState("");使用效果(() =>{console.log("效果");},[用户名]);useEffect(() => {返回 () =>{console.log("清理完毕");};}, []);const handleName = e =>{const { value } = e.target;设置名称(值);};const handleUsername = e =>{const { value } = e.target;设置用户名(值);};返回 (<div><div><input value={name} onChange={handleName}/><input value={username} onChange={handleUsername}/>

<div><div><span>{name}</span>

<div><span>{用户名}</span>

);};功能应用(){const [shouldRender, setShouldRender] = useState(true);useEffect(() => {setTimeout(() => {setShouldRender(false);}, 5000);}, []);返回 shouldRender ?<例如/>: 空值;}ReactDOM.render(, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"><;/脚本><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>

Let me explain the result of this code for asking my issue easily.

const ForExample = () => {
    const [name, setName] = useState('');
    const [username, setUsername] = useState('');

    useEffect(() => {
        console.log('effect');
        console.log({
            name,
            username
        });

        return () => {
            console.log('cleaned up');
            console.log({
                name,
                username
            });
        };
    }, [username]);

    const handleName = e => {
        const { value } = e.target;

        setName(value);
    };

    const handleUsername = e => {
        const { value } = e.target;

        setUsername(value);
    };

    return (
        <div>
            <div>
                <input value={name} onChange={handleName} />
                <input value={username} onChange={handleUsername} />
            </div>
            <div>
                <div>
                    <span>{name}</span>
                </div>
                <div>
                    <span>{username}</span>
                </div>
            </div>
        </div>
    );
};

When the ForExample component mounts, 'effect' will be logged. This is related to the componentDidMount().

And whenever I change name input, both 'effect' and 'cleaned up' will be logged. Vice versa, no message will be logged whenever I change username input since I added [username] to the second parameter of useEffect(). This is related to the componentDidUpdate()

Lastly, when the ForExample component unmounts, 'cleaned up' will be logged. This is related to the componentWillUnmount().

We all know that.

To sum, 'cleaned up' is invoked whenever the component is being re-rendered(includes unmount)

If I want to make this component to log 'cleaned up' for only the moment when it is unmount, I just have to change the second parameter of useEffect() to [].

But If I change [username] to [], ForExample component no longer implements the componentDidUpdate() for name input.

What I want to do is that, to make the component supports both componentDidUpdate() only for name input and componentWillUnmount(). (logging 'cleaned up' for only the moment when the component is being unmounted)

解决方案

Since the cleanup is not dependent on the username, you could put the cleanup in a separate useEffect that is given an empty array as second argument.

Example

const { useState, useEffect } = React;

const ForExample = () => {
  const [name, setName] = useState("");
  const [username, setUsername] = useState("");

  useEffect(
    () => {
      console.log("effect");
    },
    [username]
  );

  useEffect(() => {
    return () => {
      console.log("cleaned up");
    };
  }, []);

  const handleName = e => {
    const { value } = e.target;

    setName(value);
  };

  const handleUsername = e => {
    const { value } = e.target;

    setUsername(value);
  };

  return (
    <div>
      <div>
        <input value={name} onChange={handleName} />
        <input value={username} onChange={handleUsername} />
      </div>
      <div>
        <div>
          <span>{name}</span>
        </div>
        <div>
          <span>{username}</span>
        </div>
      </div>
    </div>
  );
};

function App() {
  const [shouldRender, setShouldRender] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setShouldRender(false);
    }, 5000);
  }, []);

  return shouldRender ? <ForExample /> : null;
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

这篇关于反应钩子 useEffect() 清理仅用于 componentWillUnmount?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆