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
Reactjs 反应挂钩。Can';t在未安装的组件上执行React状态更新_Reactjs_React Hooks - Fatal编程技术网

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
}