简体   繁体   English

从减速器 Function 中访问 Redux 中的商店的 State

[英]Accessing Store's State in Redux From Within A Reducer Function

I have a combined reducer with several reducers/states.我有一个带有几个减速器/状态的组合减速器。 Looks like follows看起来如下

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

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

in my userReducer file, i want to access the blogs state from within a function在我的 userReducer 文件中,我想从 function 中访问博客 state

this is in order to update my users state when a new blog post is saved.这是为了在保存新博客文章时更新我的用户 state。

I've tried this:我试过这个:

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

and this和这个

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

but neither are working但两者都没有工作

ultimately, upon a new blog post, i'm calling a createBlog action creator and an updateUser action creator.最终,在一篇新的博客文章中,我调用了 createBlog 操作创建者和 updateUser 操作创建者。 my user has a one to many relationship with my blog model.我的用户与我的博客 model 有一对多的关系。 I think i need to update the user's state to include the newly created blog, and figured i could just take the current blogs state, find the user and then replace their blogs with the updated state.我想我需要更新用户的 state 以包含新创建的博客,并认为我可以只获取当前的博客 state,找到用户,然后用更新的 Z9ED39E2EA931586B6A985A64E 替换他们的博客

something like this, but also stumped on part of this.像这样的东西,但也难倒其中的一部分。

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

There is a FAQ part in the Redux documentation about this issue: https://redux.js.org/faq/reducers#how-do-i-share-state-between-two-reducers-do-i-have-to-use-combinereducers Redux 文档中有一个关于此问题的常见问题解答部分: https://redux.js.org/faq/reducers#how-do-i-share-state-between-two-reducers-do-i-have-to -使用组合减速器

You could use reduce-reducers for example:例如,您可以使用reduce-reducers

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

so, as suspected, I was overly complicating things.所以,正如怀疑的那样,我把事情复杂化了。 thanks to the back and forth here, i realized that I could call another listener from another reducer.多亏了这里的来回,我意识到我可以从另一个减速器中调用另一个监听器。 thus this is how i solve my issue.因此,这就是我解决问题的方法。

in my user reducer i added a case "USER_POSTED_BLOG"在我的用户减速器中,我添加了一个案例“USER_POSTED_BLOG”

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

and then in my blog reducer i added an additional dispatch to that newly created case, which would grab all of the users and update the state after the new blog is created然后在我的博客 reducer 中,我为新创建的案例添加了一个额外的调度,它将获取所有用户并在新博客创建后更新 state

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

If you want to get your state value in the reducer you don't need getState().如果您想在减速器中获取 state 值,则不需要 getState()。 The state value is the first argument in your reducer. state 值是减速器中的第一个参数。 So you just call the state in your reducer.因此,您只需在减速器中调用 state。 If you want to get the state value in your action then you can use getState.如果您想在您的操作中获得 state 值,那么您可以使用 getState。 Also if you want to extract blogs object from the state object you are going one too far.此外,如果您想从 state object 中提取博客 object,那么您走得太远了。

Your are doing this:你正在这样做:

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

and it should be this:它应该是这样的:

const { blogs } = store.getState();

Here is an example.这是一个例子。

Reducer:减速器:

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

Action:行动:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM