Reactjs 反应挂钩。Can';t在未安装的组件上执行React状态更新
我得到这个错误:Reactjs 反应挂钩。Can';t在未安装的组件上执行React状态更新,reactjs,react-hooks,Reactjs,React Hooks,我得到这个错误: default function Test() { const [notSeenAmount, setNotSeenAmount] = useState(false) useEffect(() => { let timer = setInterval(updateNotSeenAmount, 2000) return () => clearInterval(timer) }, []) async
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
无法对未安装的组件执行React状态更新。这是
无操作,但表示应用程序内存泄漏。要解决,
取消useEffect清理中的所有订阅和异步任务
功能
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
当开始提取数据并且组件已卸载,但函数正在尝试更新已卸载组件的状态时
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
解决这个问题的最好办法是什么
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
默认功能测试(){
const[notSeenAmount,setNotSeenAmount]=useState(false)
useffect(()=>{
let timer=setInterval(updateNotSeNameCount,2000)
return()=>clearInterval(计时器)
}, [])
异步函数updateNotSeNameCount(){
让数据//我在这里获取数据
setNotSeenAmount(data)//这里有一个问题。若组件被卸载,我会得到一个错误。
}
异步函数另一个函数(){
updateNotSeName()//它也可以触发更新
}
return Push me//可以手动触发更新
}
最简单的解决方案是使用局部变量跟踪组件是否已安装。这是基于类方法的常见模式。下面是使用钩子实现它的示例:
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
function Example() {
const [text, setText] = React.useState("waiting...");
React.useEffect(() => {
let isCancelled = false;
simulateSlowNetworkRequest().then(() => {
if (!isCancelled) {
setText("done!");
}
});
return () => {
isCancelled = true;
};
}, []);
return <h2>{text}</h2>;
}
您可以在本文中找到有关此模式的更多信息。这是GitHub上展示此解决方案的React项目的内部。如果您正在从axios(使用挂钩)获取数据,并且错误仍然发生,只需将setter包装在条件中即可
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
let isRendered = useRef(false);
useEffect(() => {
isRendered = true;
axios
.get("/sample/api")
.then(res => {
if (isRendered) {
setState(res.data);
}
return null;
})
.catch(err => console.log(err));
return () => {
isRendered = false;
};
}, []);
TL;博士
这里有一个例子
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
其他答案当然有效,我只是想分享我想出的一个解决方案。
我构建了一个类似React的useState的功能,但是只有在安装组件时才会设置state。我发现它更优雅,因为您不必在组件中乱用isMounted变量
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}
安装:
用法:
const[count,setCount]=useStateIfMounted(0);
您可以在钩子的上找到更高级的文档。您的问题可能是错误地使用了setInterval,请删除函数调用:即
updateNotSeNameCount
内setInterval
@Khauri-ye旁边的()
,已修复,但问题仍然存在。我认为括号的使用在这里是有问题的-您有适当的清除代码来取消超时,所以我认为删除传递给useffect
的[]
是安全的,这是一种很好的方法,但是如何从外部触发更新呢?如何在间隔中使用它?我不明白这个问题,你能提供更多的上下文吗?@RTW你不能在useffect
内移动你的updateNotSeName
函数吗?@AndriiGolubenko我可以,但我也需要它在外面。添加了示例。@RTW我已使用使用useRef
的替代解决方案更新了答案。为什么要在顶部添加isRendered=useRef(false)?这不是必需的让isRendered=useRef(false)代码>从npm站点看,它不起作用:这个“解决方案”无法避免泄漏。甚至AbortController似乎也不是防止内存泄漏的灵丹妙药
default function Test() {
const [notSeenAmount, setNotSeenAmount] = useState(false)
useEffect(() => {
let timer = setInterval(updateNotSeenAmount, 2000)
return () => clearInterval(timer)
}, [])
async function updateNotSeenAmount() {
let data // here i fetch data
setNotSeenAmount(data) // here is problem. If component was unmounted, i get error.
}
async function anotherFunction() {
updateNotSeenAmount() //it can trigger update too
}
return <button onClick={updateNotSeenAmount}>Push me</button> //update can be triggered manually
}