繁体   English   中英

当组件可以随时卸载时,如何使用 React 管理 useEffects 中的竞争条件风险?

[英]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钩子在依赖列表改变时运行。 这就好比componentDidUpdateReact类组件。

useEffect(() => {
   // This runs every time the prop1 changes

 return () => {
  // This runs every time the prop1 changes
 };
}, [prop1]);

如果你只是空数组的依赖列表,然后它就像componentDidMountReact类组件。

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钩子会在其自己的stateprops更改时运行所有内容。

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功能的一些情况

  1. removeEventListener documentwindow上的事件removeEventListener或功能组件所做的任何其他订阅。

  2. 如果您使用的是 redux,则分派到清理商店(如果需要)。

  3. 如果有的话,要clearIntervalclearTimeout

不使用cleanup功能的一些情况

  1. 设置未挂载的功能组件的状态。

  2. 在像你的问题的情况下(根本不需要)。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM