从Reduce函数中访问Redux中的商店状态

时间:2019-11-19 02:23:09

标签: javascript reactjs redux react-redux

我有一个带有多个减速器/状态的组合减速器。看起来如下

const reducer = combineReducers({
  blogs: blogReducer,
  notification: notificationReducer,
  search: searchReducer,
  filter: filterReducer,
  users: userReducer,
  loggedUser: loginReducer
});

const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk)));

在我的userReducer文件中,我想从一个函数中访问博客状态

这是为了在保存新博客帖子时更新我的​​用户状态。

我已经尝试过了:

import store from "../store";
const { blogs } = store.getState().blogReducer.blogs;

还有这个

const { blogs } = store.getState().blogs;

但都不起作用

最终,在发布新博客后,我将调用createBlog操作创建者和updateUser操作创建者。我的用户与我的博客模型具有一对多的关系。我认为我需要更新用户状态以包括新创建的博客,并且认为我可以只采用当前博客状态,找到用户,然后用更新后的状态替换他们的博客。

类似这样的东西,但也有部分困难。

const userReducer = (state = [], action) => {
      switch (action.type) {
        case "NEW_USER":
          return [...state, action.data];
        case "UPDATE_USER":
          const { blogs } = state;
          console.log("Blogs", blogs);
          const username = action.data.id.username;
          const userBlogs = blogs.filter(b => b.user.username === username);
          const userToChange = state.find(a => a.username === username);
          const changedUser = userToChange.blogs.replace(userBlogs);
          return state.map(user =>
            user.username !== username ? user : changedUser
          );

export const updateUser = (id, blog) => {
  return async (dispatch, getState) => {
    const { blogs } = getState();
    dispatch({
      type: "UPDATE_USER",
      data: {
        id: id,
        data: blog,
        blogs
      }
    });
  };
};

3 个答案:

答案 0 :(得分:1)

Redux文档中有一个关于此问题的FAQ部分: https://redux.js.org/faq/reducers#how-do-i-share-state-between-two-reducers-do-i-have-to-use-combinereducers

您可以使用reduce-reducers例如

/* Below isn't correct web.xml syntax and will not work but is a sketch of what I am looking for. */
<error-page>
    <exception-type>*</exception-type>
    <location>/MyServlet?exctype=$exception-type$</location>
</error-page>
<error-page>
    <error-code>*</error-code>
    <location>/MyOtherServlet?errcode=$error-code$</location>
</error-page>

答案 1 :(得分:1)

所以,正如我怀疑的那样,我使事情变得过于复杂。感谢这里的来回,我意识到我可以从另一个reducer调用另一个监听器。因此,这就是我解决问题的方式。

在我的用户简化器中,我添加了一个案例“ USER_POSTED_BLOG”

 case "USER_POSTED_BLOG":
      return [...action.data];

然后在我的Blog Reducer中,我向该新创建的案例添加了一个额外的调度,它将捕获所有用户并在创建新博客后更新状态

export const createBlog = content => {
  return async dispatch => {
    const newBlog = await blogService.create(content);
    dispatch({
      type: "NEW_BLOG",
      data: newBlog
    });
    const updatedUsers = await userService.getAll();
    dispatch({
      type: "USER_POSTED_BLOG",
      data: updatedUsers
    });
  };
};

答案 2 :(得分:0)

如果要在化简器中获取状态值,则不需要getState()。状态值是化简器中的第一个参数。因此,您只需要在化简器中调用状态即可。如果要在操作中获取状态值,则可以使用getState。另外,如果您想从状态对象中提取博客对象,那也就太过分了。

您正在这样做:

const { blogs } = store.getState().blogs;

应该是这样:

const { blogs } = store.getState();

这里是一个例子。

减速器:

const initialState = {
  //your initial state
}

export default (state = initialState, action) => {
  switch(action.type){
    case "UPDATE_USER":
      // just use the state object
      const { blogs } = state;
      const username = action.data.id.username;
      const userToChange = blogs.find(a => a.username === username);
      const blogsNeedToChange = userToChange.blogs
      const changedUserBlogs = ?????????????
      return state.map(user =>
        user.username !== username ? user : changedUserBlogs
      );
  }
}

操作:

export const updateUser = (id, blog) => {
  return async (dispatch, getState) => {
    const { blogs } = getState();
    dispatch({
      type: "UPDATE_USER",
      data: {
        id: id,
        data: blog,
      }
    });
  };
};