[英]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.