我试图了解使用useEffect清理的确切反应以及用于什么目的。您能否通过添加清理来帮助我修复代码
据我所知在关闭订阅的API调用中使用了它。仍然无法弄清其使用原因以及使用方法。
useEffect(() => {
async function onLoad() {
try {
const examSessions = await loadSessions(id);
setSessions(examSessions);
console.log(`examSession`,examSessions)
} catch (e) {
// onError(e);
console.log(e)
}
setIsLoading(false);
}
onLoad()
}, [id])
function loadSessions(id) {
const result = API.get("vce", `/session/${id}`)
return result
}
答案 0 :(得分:1)
如果不进行清理,即使已卸载组件,效果也将永远做下去。
这对于可能负责设置网络事物(例如Web套接字连接)或使用fetch
请求数据的复杂组件很重要。如果您没有取消或关闭这些资源,这些资源将仍然处于打开状态并可能发送信号。
考虑以下示例,我们可以在其中切换选中的Foo
组件。清理掉注释后,即使它已卸载,我们仍会看到“ Tick”,因为我们没有时间清理间隔。
实际上,如果重新切换Foo
,您将开始在控制台中看到更多的“滴答”,因为现在有2个以上的滴答声。假设这是一个Web套接字,并且每次重新安装时我们都在计划一个新的心跳信号;服务器会对我们的应用心跳感到非常生气。
const {
useState,
useEffect,
createElement
} = React;
const {
render
} = ReactDOM;
const Foo = () => {
const [t, setT] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
console.log("Tick");
setT(currT => currT + 1);
}, 1000);
// Without the following, you will see "Tick" forever because it isn't cleaned up
//return () => clearInterval(interval);
}, []);
return createElement("div", {}, t);
};
const App = () => {
const [should, setShould] = useState(true);
return createElement("div", null,
createElement("button", {
onClick: () => setShould(currShould => !currShould)
}, "toggle"),
should ? createElement(Foo) : null
);
};
render(
createElement(App),
document.getElementById('app')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>
将以下示例与 做 具有以下清理操作的示例进行比较: 将 您可以切换Foo
组件。
const {
useState,
useEffect,
createElement
} = React;
const {
render
} = ReactDOM;
const Foo = () => {
const [t, setT] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
console.log("Tick");
setT(currT => currT + 1);
}, 1000);
// Without the following, you will see "Tick" forever because it isn't cleaned up
return () => clearInterval(interval);
}, []);
return createElement("div", {}, t);
};
const App = () => {
const [should, setShould] = useState(true);
return createElement("div", null,
createElement("button", {
onClick: () => setShould(currShould => !currShould)
}, "toggle"),
should ? createElement(Foo) : null
);
};
render(
createElement(App),
document.getElementById('app')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>
答案 1 :(得分:0)
您无需在此处使用清理挂钩。您尚未订阅任何内容。当您对某个内容使用useEffect订阅并且不取消订阅组件破坏时,此订阅将继续侦听远程源,窃取设备内存和用户数据。
要对其进行测试,您只需在按钮上附加一个单击侦听器,安装/卸载组件(无需刷新页面),然后在chrome dev工具中查看订阅/侦听器列表的增长方式即可。
编辑: 试试这个
useEffect(() => {
let unmounted = false;
async function onLoad() {
try {
const examSessions = await loadSessions(id);
setSessions(examSessions);
console.log(`examSession`,examSessions)
} catch (e) {
// onError(e);
console.log(e)
}
if(!unmounted)setIsLoading(false);
}
onLoad()
return ()=> unmounted = true;
}, [id])