Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/408.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 处理';Can';t在未安装的组件上调用setState';反应警告_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 处理';Can';t在未安装的组件上调用setState';反应警告

Javascript 处理';Can';t在未安装的组件上调用setState';反应警告,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,你们可能已经看到了这个错误,如果不是的话,通常看起来是这样的: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. 首先,这不是一个关于错误意味着什么的问题。在我看来,在某些情况下,这个警告(据我所知)有点不合理 考虑一下这个组件 () => { const [foo, set

你们可能已经看到了这个错误,如果不是的话,通常看起来是这样的:

Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
首先,这不是一个关于错误意味着什么的问题。在我看来,在某些情况下,这个警告(据我所知)有点不合理

考虑一下这个组件

() => {
  const [foo, setFoo] = useState(false)

  return (
    <>
      <p>Is foo: {foo}</p>
      <button onClick={() => {
        setFoo(true)
        window.setTimeout(() => setFoo(false), 1000)
      }}>Click me</button>
    </>
  )
}
constusesafestate=(defaultState:T):[T,(newState:T)=>void]=>{
常量[状态,设置状态]=使用状态(默认状态)
const isMounted=useIsMounted()
返回[
国家,,
(新闻状态:T)=>{
如果(已安装){
设置状态(新闻状态)
}
},
]
}
通过将第一个示例更改为使用
useSafeState
,它会自动进行检查,有效地抑制警告。你们觉得这个怎么样?“使用安全状态”在功能上没有任何作用,因为react警告指出它是一个“否”操作。我觉得当人们忘记从useEffect中取消设置间隔时,该警告就在那里,但对于这些其他场景,我们被迫做一些像这样愚蠢的事情,只是为了摆脱警告

思考?

提供了一些关于如何以及为什么需要进行清理的示例

之前,我们研究了如何表达不需要药物的副作用 任何清理。然而,有些效果确实如此。例如,我们可能想 设置对某些外部数据源的订阅。在这种情况下,它 清理非常重要,这样我们就不会引入内存泄漏! 让我们比较一下如何使用类和钩子来实现它

虽然
setTimeout
示例可能是人为设计的,但最好根据需要处理清理,而不是使用
useSafetState
之类的工具,因为这不一定会避免潜在的内存泄漏,即使在这种情况下它会阻止对
setState
的调用。可能会让你免于崩溃,或者让你的用户运行更少的东西来改善他们在你网站上的体验

使用
useffect
的返回值,您可以通过返回执行清理的函数,在组件最终卸载时清除当前计时器

您的组件可能如下所示:

Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
()=>{
const[foo,setFoo]=useState(false)
const timeout=useRef(null);
useffect(()=>{
return()=>{
if(超时。当前){
clearTimeout(timeout.current);
}
}, [])
常量handleClick=()=>{
setFoo(真);
if(超时。当前){
clearTimeout(timeout.current);
}
timeout.current=setTimeout(()=>setFoo(false),1000);
}
返回(
是foo:{foo}

点击我 ) }
您需要清除useEffect中计时器的返回值:

工作示例

函数TimeoutExample(){
const[foo,setFoo]=useState(false)
const counterRef=useRef(null);
useffect(()=>{
return()=>{
if(反向参考电流){
clearTimeout(计数器参考电流);
反向参考电流=零
}
}
}, []);
const handleButtonClick=()=>{
if(反向参考电流)返回;
setFoo(真);
counterRef.current=setTimeout(()=>setFoo(false),1000);
};
返回(
是foo:{foo}

点击我 ) }
您需要清除useEffects中的设置超时return@DerekPollard嘿,谢谢你的回答。我的问题更多的是关于为什么/如果我们在某些情况下确实需要清除它。特别是那些为响应像onClick这样的事件而创建超时的情况,而不是效果。如果你认为有必要创建一个separa使用effect并跟踪事件句柄(有点凌乱)您能解释一下原因吗?是的,您需要这样做,这是内存泄漏的一个指示器。负责并清理不再使用的资源总是好的。在这种情况下,您将保留对
setFoo
的引用,以防止它被清空。在这里,您使用了一个超时,因此,超时最终会运行。但是它会如果有人决定将foo状态移出此组件,并且您离开此组件后会影响状态,因为计时器没有停止,则uld也会导致故障。如果您是一个坏用户,并在此处多次单击该按钮,则它将失去对现有超时的跟踪,因为它只跟踪最后一个超时。因此,如果您单击10次(在1000毫秒内)然后卸载组件,只有最后一个计时器会被清除,接下来应该有9条警告:)基于单击的useEffect被认为是不好的做法;导致DeX的计时器的启动原因并不明显issues@JusticeDeX问题?DX?开发人员经验?还是其他问题?我同意这在某种意义上并不明显。即使在源代码处有依赖项数组提示。请详细说明错误做法tho!是的,开发人员体验-此类副作用应保留在useCallback或arrow函数中(取决于rerender管理的特殊性)。否则,您最终会依赖于与单击处理程序相切的外部副作用。@这是正确的,尤其是如果您希望在没有相同影响的情况下在此之外更改它。但该示例的规模有点小。但同意共同定位副作用。因此,创建ha更有意义ndler函数与另一个答案类似。例如,如果自上次交互后,ndler函数应始终显示1秒,则它也不会显示。
const useSafeState = <T extends unknown>(defaultState: T): [T, (newState: T) => void] => {
  const [state, setState] = useState<T>(defaultState)
  const isMounted = useIsMounted()

  return [
    state,
    (newState: T) => {
      if (isMounted) {
        setState(newState)
      }
    },
  ]
}

function TimeoutExample() {
  const [foo, setFoo] = useState(false)
  const counterRef = useRef(null);

  useEffect(() => {
    return () => {
      if (counterRef.current) {
        clearTimeout(counterRef.current);
        counterRef.current = null
      }
    }
  }, []);

  const handleButtonClick = () => {
    if (counterRef.current) return;
    setFoo(true);
    counterRef.current = setTimeout(() => setFoo(false), 1000);
  };

  return (
    <>
      <p>Is foo: {foo}</p>
      <button onClick={handleButtonClick}>Click me</button>
    </>
  )

}