【发布时间】:2023-04-10 20:00:02
【问题描述】:
在 redux 状态和基于类的组件中使用标志时,生活是美好的。您在 componentWillMount 中启动 API 调用,当组件被挂载并且 render() 函数运行时,您在 redux 中正确设置了标志,这意味着不会出现不需要的内容 (FUC)。
这很好,但我们现在使用的是函数式组件。在这种情况下,我们通过 useEffect() 运行 API 调用,这意味着我们只在第二次渲染时在 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 来初始化存储。这意味着您必须确保在退出组件时始终将其返回为 true。如果在多个组件中使用相同的标志,这可能会导致错误。这不是一个理想的解决方案。
使用 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 似乎没有一种简单的方法来实现这一点,其中使用生成器而不是承诺。在 redux-saga 中处理带有功能组件的加载标志的最佳实践是什么?
【问题讨论】:
-
问题:你有充分的理由在这里使用 saga 吗?一般来说,我们只推荐它用于非常复杂的用例,即使那样你也应该在适用的情况下将它与 thunk 混合使用(参见redux.js.org/style-guide/style-guide/…)。此外,仅供参考,官方 Redux Toolkit 附带完整的 api 缓存解决方案,因此如果您使用它,您将不需要 thunk 或 saga 来获取数据。 redux-toolkit.js.org/rtk-query/overview
-
@phry 对于 99% 的项目,我总是更喜欢 redux-toolkit 和 thunk。我目前正在支持一个使用 redux-saga 的遗留项目,它绝不需要使用 redux-saga。重写将是一项痛苦而漫长的工作。
标签: reactjs redux redux-saga