- 首页
- 其他开发
- 反应钩子 useEffect() 清理仅用于 componentWillUnmount?
反应钩子 useEffect() 清理仅用于 componentWillUnmount?
[英] react hooks useEffect() cleanup for only componentWillUnmount?
本文介绍了反应钩子 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屋!
查看全文