我刚刚开始使用redux
和react-redux
做一些实验。
注意:我使用的是挂钩,因此我使用的是useSelector()
中的useDispatch()
和react-redux
自定义挂钩。
想象一下,我有某种状态可以基于blogPost
从数据库中获取slug
。
我的状态。博客帖子:
{
loading: false, // TRUE while fetching
error: null, // TO keep network errors
blogPost: null // TO keep the blogPost
}
BlogPostContainer.js
我正在useEffect
内调度动作和异步调用。
注意1::我正在手动执行异步作业,因为我还没有使用redux-thunk
。
注意2::我正在使用react-router-dom
,所以这些sl来自props.match.params.slug
。
示例:myApp.net/blog/some-blog-post-slug
// ...
const { loading, error, blogPost } = useSelector(state => state.blogPost);
const dispatch = useDispatch();
useEffect(() => {
dispatch({ type: "GET_BLOGPOST_START", payload: props.match.params.slug }); // START ACTION
mockAPI(props.match.params.slug)
.then((result) => {
dispatch({ type: "GET_BLOGPOST_SUCCESS", payload: result }); // SUCCESS ACTION
})
.catch((err) => {
dispatch({ type: "GET_BLOGPOST_FAIL", payload: err }); // FAIL ACTION
})
}, [dispatch,props.match.params.slug]);
// RETURN STATEMENT
return (
loading ?
<div>Loading...</div>
: error ?
<ErrorPage/>
: <BlogPostPage blogPost={blogPost}/>
);
问题
这对于第一个加载的blogPost正常工作(因为此时状态完全为空)。
现在想象一下,我回到首页并单击另一个BlogPost。
从第二次开始,当我的BlogPostContainer
呈现时,我的状态已经存在(blogPost
或error
上次为上一个BlogPost子弹加载的状态)。
因此,在我的useEffect
运行之前,我在屏幕上看到了闪烁的信息。当它运行时,loading
动作将GET_BLOGPOST_START
设置为true,我将看到加载情况。
我想立即查看加载页面。不会闪烁任何旧状态数据。
人们在使用redux时通常如何处理?
我需要一个本地 loading
状态吗?
在卸下组件时,我应该调度一个将loading
转换为true
的操作吗?因此,当我的组件再次安装到下一个true
时,它已经是slug
了吗?
我应该使用useLayoutEffect
,以便效果在渲染之前运行,并且看不到闪烁吗? (它可以工作,但感觉不对)。
针对这种情况的最佳解决方案是什么?
额外
我的减速机:
const initialState = {
loading: false,
error: null,
blogPost: null
};
function getBlogPostReducer(state = initialState, action) {
switch (action.type) {
case "GET_BLOGPOST_START": // SET LOADING TO TRUE
return {
...initialState,
loading: true
};
case "GET_BLOGPOST_SUCCESS": // SET BLOGPOST and LOADING TO FALSE
return {
...initialState,
loading: false,
blogPost: action.payload
};
case "GET_BLOGPOST_FAIL": // SET ERROR and LOADING TO FALSE
return {
...initialState,
loading: false,
error: action.payload
};
default:
return state;
}
}
export default getBlogPostReducer;
答案 0 :(得分:3)
在useEffect
中返回一个清理函数,当组件卸载时,该函数将分派清晰的博客文章操作:
useEffect(() => {
dispatch({ type: "GET_BLOGPOST_START", payload: props.match.params.slug }); // START ACTION
mockAPI(props.match.params.slug)
.then((result) => {
dispatch({ type: "GET_BLOGPOST_SUCCESS", payload: result }); // SUCCESS ACTION
})
.catch((err) => {
dispatch({ type: "GET_BLOGPOST_FAIL", payload: err }); // FAIL ACTION
})
return () => dispatch({ type: "CLEAR_BLOGPOST" });
}, [dispatch,props.match.params.slug]);
reduce处理程序应该从状态中同时删除error
和blogpost
条目:
case "CLEAR_BLOGPOST":
return initialState;