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