我正在检查是否已卸载组件,以便不调用状态更新功能。
const ref = useRef(false)
useEffect(() => {
ref.current = true
return () => {
ref.current = false
}
}, [])
....
if (ref.current) {
setAnswers(answers)
setIsLoading(false)
}
....
isMounted
,但true
始终为false const [isMounted, setIsMounted] = useState(false)
useEffect(() => {
setIsMounted(true)
return () => {
setIsMounted(false)
}
}, [])
....
if (isMounted) {
setAnswers(answers)
setIsLoading(false)
}
....
与第一个选项相比,为什么第二个选项不起作用?
答案 0 :(得分:0)
在没有较大上下文的情况下很难知道,但我认为您甚至不需要知道是否已装入某些内容。 useEffect(() => {...}, [])
会在挂载时自动执行,您可以放任何所需的内容,直到挂载到该效果中为止。
答案 1 :(得分:0)
请仔细阅读此答案,直到最后。
似乎您的组件正在渲染多次,因此isMounted
状态始终变为false,因为它不会在每次更新时都运行。它只运行一次就可以卸载。因此,您将在第二个选项数组中传递状态:
}, [isMounted])
现在,它将监视状态并在每次更新时运行效果。但是为什么第一种选择有效?
这是因为您使用的是useRef
,它是异步的,而不是异步的useState
。如果不清楚,请再次阅读有关useRef的文档:
之所以有效,是因为useRef()创建了一个纯JavaScript对象。 useRef()和自己创建{current:...}对象之间的唯一区别是useRef将在每个渲染器上为您提供相同的ref对象。
顺便说一句,您不需要清理任何东西。 DOM更改,第三方api反射等都需要清理过程。但是您不必养成清理状态的习惯。因此,您可以使用:
useEffect(() => {
setIsMounted(true)
}, []) // you may watch isMounted state
// if you're changing it's value from somewhere else
使用useRef
钩子时,最好进行清理过程,因为它与dom变化有关。
答案 2 :(得分:0)
如果您要为此使用小型库,则react-tidy
有一个自定义钩子,专门用于执行名为useIsMounted
的钩子:
import React from 'react'
import {useIsMounted} from 'react-tidy'
function MyComponent() {
const [data, setData] = React.useState(null)
const isMounted = useIsMounted()
React.useEffect(() => {
fetchData().then((result) => {
if (isMounted) {
setData(result)
}
})
}, [])
// ...
}
免责声明。我是该库的作者。
答案 3 :(得分:0)
我编写了这个自定义钩子,可以检查当前是否已安装组件,如果您需要长时间运行并且该组件可能在完成并更新UI状态之前已被卸载,则很有用。
import { useCallback, useEffect, useRef } from "react";
export function useIsMounted() {
const isMountedRef = useRef(true);
const isMounted = useCallback(() => isMountedRef.current, []);
useEffect(() => {
return () => void (isMountedRef.current = false);
}, []);
return isMounted;
}
function MyComponent() {
const [data, setData] = React.useState()
const isMounted = useIsMounted()
React.useEffect(() => {
fetch().then((data) => {
// at this point the component may already have been removed from the tree
// so we need to check first before updating the component state
if (isMounted()) {
setData(data)
}
})
}, [...])
return (...)
}
答案 4 :(得分:0)
这清除了我的错误消息,在我的 useEffect 中设置 return 取消订阅和异步任务。
import React from 'react'
const MyComponent = () => {
const [fooState, setFooState] = React.useState(null)
React.useEffect(()=> {
//Mounted
getFetch()
// Unmounted
return () => {
setFooState(false)
}
})
return (
<div>Stuff</div>
)
}
export {MyComponent as default}