Javascript 访问存储';从Reducer函数中删除Redux中的状态

Javascript 访问存储';从Reducer函数中删除Redux中的状态,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,我有一个带有几个减速器/状态的组合减速器。看起来如下 const reducer = combineReducers({ blogs: blogReducer, notification: notificationReducer, search: searchReducer, filter: filterReducer, users: userReducer, loggedUser: loginReducer }); const store = createStore(

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

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

const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk)));
在我的userReducer文件中,我希望从函数中访问blogs状态

这是为了在保存新博客文章时更新我的用户状态

我试过这个:

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

const { blogs } = store.getState().blogs;
但两者都不起作用

最后,在一篇新的博客文章中,我给createBlog action创建者和updateUser action创建者打电话。我的用户与我的博客模型有一对多的关系。我想我需要更新用户的状态以包含新创建的博客,我想我可以只获取当前博客的状态,找到用户,然后用更新的状态替换他们的博客

像这样的事情,但也有一部分被难住了

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
      }
    });
  };
};

如果要在reducer中获取状态值,则不需要getState()。state值是reducer中的第一个参数。所以你只需要在你的减速器中调用状态。如果希望在操作中获取状态值,则可以使用getState。另外,如果您想从state对象中提取blogs对象,那么您做得太过分了

您正在这样做:

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,
      }
    });
  };
};

Redux文档中有一个关于此问题的常见问题部分:

例如,您可以使用:

// In this reducer, the state argument represents your root state
// Here you can handle actions which need to access multiple slice of the root state
const specializedReducer = (state, action) => {
  switch (action.type) {
    case "UPDATE_USER":
      const { blogs, users } = state;
      // proceed with your code here
  }
}

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

const rootReducer = reduceReducers(specializedReducer, reducer);

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

所以,正如我所怀疑的,我把事情复杂化了。多亏了这里的反复,我意识到我可以从另一个地方给另一个听众打电话。这就是我解决问题的方法

在我的用户减速器中,我添加了一个案例“user\u POSTED\u BLOG”

然后在我的blog reducer中,我在新创建的案例中添加了一个额外的分派,它将捕获所有用户,并在新blog创建后更新状态

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
    });
  };
};

getState
是传递给
thunk
的第二个参数(在
dispatch
之后)。你不应该在操作中导入存储。而且,
thunk
可以
dispatch
任意多的操作,所以这可能是操作的最佳方法。@Adam我在他的存储中没有看到他应用了thunk。我只是快速复制了他的代码,但编辑了我的答案。我也同意他可能应该保持减速机的纯净,并执行操作中的所有逻辑,但他的问题是如何获得减速机中的状态,我不打算重构他的代码。我只是在action中添加了getState,这样他就可以看到在action中获取状态与在reducer中获取状态之间的区别。让OP在另一个reducer中获取属于一个reducer的状态违背了redux的整个核心概念。这是JavaScript,你可以做任何你想做的事情,但是不要。从thunk中分派多个操作,或收听blogs reducer中的
UPDATE\u USER
操作。通过暗示OP正在做什么是ok,不仅对OP,而且对任何碰巧遇到这个问题的人来说,都是一种非常糟糕的做法。不要仅仅因为你不想“重构他的代码”就给出错误的答案。@JohnRogerson我认为这与你的动作创建者无关,可能与你的减缩器有关,但我可能错了。如果让我猜的话,它可能就是你的userReducer中的return语句。您正在通过状态进行映射,在映射函数中,您将用户作为参数,但您将通过还原程序进行映射,而不是用户尝试state.users.map。也就是说,我认为你应该在你的操作中完成所有的逻辑,然后将完成的数据传递给你的减速机,这会使事情变得更容易。你的reducer应该是纯的,没有逻辑,只有数据。我完全不清楚你想做什么,但所有reducer都接收所有操作,所以你的
博客
reducer可以响应你的
更新用户
操作,如果有帮助的话。如果不直接导入存储,您就无法访问当前reducer状态的根键之外的内容。如果您要做大量的b/c工作,您可能需要查看redux传奇,因为b/c库使异步处理更加简单。@DovRine-用户在这里没有做任何
async
。他们得到
async dispatch=>
是因为他们从网上的其他地方复制了它,而不是因为他们在做
async
的事情。OP应1)从
thunk
发送多个操作,或2)收听博客中的
UPDATE\u USER
操作。每个减速器必须注意其自身的状态。编辑:第三个(可能是最好的)选项-是的,我显然是redux/thunk等的新用户,只是沿着完整的堆栈开放课程。我的主要问题是,当我提交一篇新的博客文章时,“博客”状态正在更新,而“用户”状态则没有更新,我需要该状态才能显示具有关联日志的完整用户列表blogs@JohnRogerson-只需添加
case“UPDATE\u USER”:
在您的博客减速器中,您的所有减速器都会收到相同的操作。
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
    });
  };
};