[英]How to manage the risk of race conditions in useEffects when a component can un-mount at any time, with React?
使用 TypeScript 4、React 17(我寫這些行時的當前版本)。
假設我有以下組件。
該組件位於 React Navigation 條件堆棧導航器之后。 這意味着如果用戶取消連接,該組件將自動卸載並與整個 UI 一起顯示,而是顯示登錄屏幕。
這是由應用程序根導航器中的此類代碼管理的:
user ? (
<RootStack.Screen name="Home" component={HomeScreen} />
) : (
<RootStack.Screen name="Login" component={LoginScreen} />
)
這是在主屏幕上打印的組件。
我在另一個項目中遇到了一些問題,我的一個朋友建議在組件卸載時始終處於這種卸載狀態,並且存在競爭條件的風險。
我有一些競爭條件問題,但到目前為止,在所有組件上添加卸載都沒有解決。
我的朋友是否應該繼續將這些卸載或者像以下組件這樣簡單和同步的情況下不需要它?
interface Props {
prop1: number
}
const MyFunctionalComponent: FC<Props> = ({prop1 = 0}: Props) => {
const [stateVariable, setStateVariable] = useState<string>('initial value')
useEffect(() => {
let mounted = true
if (mounted) {
// We are synchronous, no await there.
const newStateVariable: string = stringify(prop1)
setStateVariable(newStateVariable)
}
return (): void => {
mounted = false
}
}, [prop1])
return <Text>{ stateVariable }</Text>
}
您對此有何用途和了解?
謝謝
您不必使用useEffect
鈎子的清理來執行此操作。
useEffect
鈎子在依賴列表改變時運行。 這就好比componentDidUpdate
在React
類組件。
useEffect(() => {
// This runs every time the prop1 changes
return () => {
// This runs every time the prop1 changes
};
}, [prop1]);
如果你只是空數組的依賴列表,然后它就像componentDidMount
在React
類組件。
useEffect(() => {
// This runs when component mounts
// see there is no dependency passed for this
return () => {
// This runs when component un mounts
// Do your cleanup here as it is run only on unmount
};
}, []);
如果未傳遞空數組或依賴項列表,則useEffect
鈎子會在其自己的state
或props
更改時運行所有內容。
useEffect(() => {
// Runs every time the component renders
});
我想現在你的案子已經很清楚了。
您不必使用mounted
變量本身。 每次當您的prop1
更改時, stateVariable
都會更新。
const MyFunctionalComponent: FC<Props> = ({prop1 = 0}: Props) => {
const [stateVariable, setStateVariable] = useState<string>('initial value')
useEffect(() => {
// We are synchronous, no await there.
const newStateVariable: string = stringify(prop1)
setStateVariable(newStateVariable)
}, [prop1])
return <Text>{ stateVariable }</Text>
}
需要使用cleanup
功能的一些情況
removeEventListener
document
或window
上的事件removeEventListener
或功能組件所做的任何其他訂閱。
如果您使用的是 redux,則分派到清理商店(如果需要)。
如果有的話,要clearInterval
或clearTimeout
。
不使用cleanup
功能的一些情況
設置未掛載的功能組件的狀態。
在像你的問題的情況下(根本不需要)。
在MyFunctionalComponent
的情況下,您應該調用useMemo()
而不是useState()
和useEffect()
:
interface Props {
prop1: number
}
const MyFunctionalComponent: FC<Props> = ({ prop1 = 0 }: Props) => {
const computedVariable = useMemo(() => {
return stringify(prop1)
}, [prop1])
return <Text>{ computedVariable }</Text>
}
useState()
僅在您需要有狀態值時才需要。 在您提供的示例中, stateVariable
完全依賴於prop1
,沒有任何延遲,因此它實際上根本不需要有狀態。 useMemo()
在技術上也是一個有狀態的鈎子,但只是為了在輸入不變時避免不必要的重復昂貴的計算。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.