如何在 reducer 中调度错误操作?

How to dispatch error action within the reducer?

我正在学习 Redux + Redux 工具包。我需要一个建议。

非常基本的例子。我有一些状态切片:

const postsSlice =  createSlice({
  name: 'posts',
  initialState: [],
  reducers: {
    // ... some other reducers

    updatePost(state, payload) {
      const { id, title, content } = payload;
      const existingPost = state.find(post => post.id === id);

      if (existingPost) {
        existingPost.title = title;
        existingPost.content = content;
      } else {
        // I want to dispatch some error action because user tries to edit a post that does not exist!
      }
    }
  }
});

所以我有 updatePost reducer,我将其导出为 action creator。它使用给定的 id 更新 post。如果找不到带有 id 的 post,我想显示错误消息。假设我有另一个带有相应操作的消息状态片。但是我如何从我的减速器中发送它呢?我应该吗?对我来说这感觉像是一种反模式。

到目前为止,我正在考虑为我的 updatePost 动作创建器导出包装器(thunk?)。像这样:

export const updatePost = payload => (dispatch, getState) => {
  const { id } = payload;
  const existingPost = getState().posts.find(post => post.id === id);
  
  if (existingPost) {
    dispatch(postsSlice.actions.updatePost(payload));
  } else {
    dispatch(showError('some invalid post error'));
  }
};

这个解决方案对我来说很难看。首先,它对整个商店状态 (getState()) 进行操作。而且,我不确定这是否是我应该使用 thunk 的目的。看起来它们更适合异步数据获取等内容。

But how I can dispatch it from my reducer? And should I? It feels like an anti-pattern for me.

你就在这里。你永远不应该从 reducer 发送一个动作。

你的 thunk 例子不错。但是既然你在征求意见,我个人的意见是处理编辑 post 的组件应该负责确保 post 存在(你可以使用选择器来做到这一点)。如果 post id 无效,我们应该阻止编辑发生。不需要将无效的 post 错误作为操作发送,这将在组件内部处理。

const PostEditor = ({id}) => {

    const current = useSelector(getPost(id));

    const dispatch = useDispatch();

    return (
        <div>
            {!! current ? 
                <EditPost ..../>
                :
                <div>Error: Invalid Post ID #{id}</div>
            }
        </div>
    )
}