使用 Redux saga 和 React 功能组件加载标志

Loading flags with Redux saga and React functional components

在 redux 状态和基于 class 的组件中使用标志时,生活是美好的。你在 componentWillMount 中开始你的 API 调用,当组件被安装和 render() 函数 运行s 时,你在 redux 中正确设置了你的标志,这意味着没有闪光不需要的内容 (FUC)。

很好,但是我们现在使用的是功能组件。在这种情况下,我们 运行 API 通过 useEffect() 调用,这意味着我们仅在第二次渲染时在 redux 中设置标志。以简单组件为例:

function SimpleComponent() {
   const isLoading = useSelector(selectIsLoading);
   const dispatch = useDispatch();

   useEffect(() => {
     dispatch(startApiRequest());
   },[dispatch]);

   if (isLoading) {
     return <LoadingComponent />;
   }

   return <ContentThatWillBreakIfApiCallIsNotFinished />;
}

这段代码的行为如下:

render 1: isLoading is false, you show broken content.
after render 1: useEffect runs, sets isLoading to true
render 2: isLoading is true, you no longer show broken content

一个简单的解决方案是将 isLoading 设置为 true 来初始化商店。这意味着您必须确保在退出组件时始终 return 它为真。如果在多个组件中使用相同的标志,这可能会导致错误。这不是一个理想的解决方案。

借助 redux-thunk,我们可以使用具有内部 isLoading 标志且不在 redux 中设置标志的自定义挂钩。类似于:

const apiCallWithLoadingIndicator = () => {
  const [isLoading, setIsLoading] = useState(true);
  const dispatch = useDispatch();

  useEffect(() => {
    (async () => {
      await dispatch(asyncThunkReturningPromise());
      setIsLoading(false);
    })()
  }, [setIsLoading, dispatch]);
  return isLoading;
}

似乎没有使用 redux-saga 实现此目的的简单方法,其中使用生成器而不是 promises。在 redux-saga 中使用功能组件处理加载标志的最佳实践是什么?

通常:componentWillMount 已被弃用多年,可能会在 React 18 中删除 - 你也不应该在 class 组件中使用它。

就是说,通常它有助于从初始状态开始,比如“未初始化”的状态值告诉你,虽然它没有加载,但它甚至还没有开始做任何事情,并且处理方式与组件中的“加载”相同。