从操作中访问 Redux 状态,我应该将商店设置为全局吗?
Redux state access from actions, should i make store global?
我对 redux 很陌生,这是我的数据库的简化版本:
store: {
userID: 1234,
userData: { // fetch-ed from api
foo,
bar,
...
}
关于userID的变化,我想获取userData,我找到了一个名为redux-thunk的库,它可以使dispatch-es异步(我正在获取数据),但是对于获取URL 我需要商店的用户 ID,但我不知道如何直接从操作中访问它。
我每次调用它时都应该将它传递给动作吗
dispatch(updateUser(store.getState().userID))
?
我不确定我是否完全理解这个问题,但在我看来您的方向是正确的,但可能需要重新考虑您商店的结构。如果您有定义 reducer 的代码,那么在此处以及您使用 connect
访问组件 props 中的此数据的地方看到它会很有帮助。
除此之外,这是我的建议。
听起来您正在寻找能够显示用户配置文件并在它们之间切换的功能。在这种情况下,我建议您使用用户列表来构建您的商店,而不是使用被覆盖的单个用户对象。它看起来像这样:
{
users: [{ id: '123', name: 'Hello' }, { id: '234', name: 'Goodbye' }],
currentUserId: '123'
}
在这种情况下,要切换您在特定页面上显示的用户(或您登录的用户),您只需更改您 select,而不是更新商店以用新用户覆盖 user
。在 UI 元素更新当前用户而不更新 URL 的情况下(即某些调用 dispatch(updateCurrentUserId('234'))
,那么您的组件应该只是 select 来自 users
基于此在商店中键入:
const MyComponent = ({ user }) => (
<div>User name is { user.name }</div>
);
const mapStateToProps = ({ users, currentUserId ) => ({
user: users.find(u => u.id === currentUserId)
});
export default connect(mapStateToProps)(MyComponent);
这样,要切换代表哪个用户,您只需更改商店中的 currentUserId
。
假设您已经从 API 中获取了用户列表。如果你一次获取一个,你确实可以使用 redux thunk。我仍然建议将用户存储为列表,这样您就可以轻松地在它们之间切换。在这种情况下,你的 thunk 会想要从商店中获取用户(如果它存在),或者如果它不存在则获取它。像这样:
// Alternately, you could pass *no* argument, and grab currentUserId
// from state like users below
const getUser = userId => (dispatch, getState) => {
const localUsers = getState().users;
const localUser = localUsers.find(u => u.id === userId);
if (localUser) {
// Because the user is in the store, we just need to point the frontend
// to the right user.
dispatch(updateCurrentUserId(userId));
} else {
// Fetch the user, add them to the store, and then point to them.
fetch(`whatever.com/users/${userId}`)
.then(response => {
dispatch(addUser(response.data));
dispatch(updateCurrentUserId(userId));
}).catch(err => /* do something */);
}
}
此 thunk 允许您根据您的用户是否存在于数据中来有条件地和异步地运行。但是,与您的设计不同的是,您不会在新用户到来时覆盖当前用户。
请注意,您也可以在没有 currentUserId
的情况下执行此操作,而不是仅从 URL 解析用户 ID。
我对 redux 很陌生,这是我的数据库的简化版本:
store: {
userID: 1234,
userData: { // fetch-ed from api
foo,
bar,
...
}
关于userID的变化,我想获取userData,我找到了一个名为redux-thunk的库,它可以使dispatch-es异步(我正在获取数据),但是对于获取URL 我需要商店的用户 ID,但我不知道如何直接从操作中访问它。
我每次调用它时都应该将它传递给动作吗
dispatch(updateUser(store.getState().userID))
?
我不确定我是否完全理解这个问题,但在我看来您的方向是正确的,但可能需要重新考虑您商店的结构。如果您有定义 reducer 的代码,那么在此处以及您使用 connect
访问组件 props 中的此数据的地方看到它会很有帮助。
除此之外,这是我的建议。
听起来您正在寻找能够显示用户配置文件并在它们之间切换的功能。在这种情况下,我建议您使用用户列表来构建您的商店,而不是使用被覆盖的单个用户对象。它看起来像这样:
{
users: [{ id: '123', name: 'Hello' }, { id: '234', name: 'Goodbye' }],
currentUserId: '123'
}
在这种情况下,要切换您在特定页面上显示的用户(或您登录的用户),您只需更改您 select,而不是更新商店以用新用户覆盖 user
。在 UI 元素更新当前用户而不更新 URL 的情况下(即某些调用 dispatch(updateCurrentUserId('234'))
,那么您的组件应该只是 select 来自 users
基于此在商店中键入:
const MyComponent = ({ user }) => (
<div>User name is { user.name }</div>
);
const mapStateToProps = ({ users, currentUserId ) => ({
user: users.find(u => u.id === currentUserId)
});
export default connect(mapStateToProps)(MyComponent);
这样,要切换代表哪个用户,您只需更改商店中的 currentUserId
。
假设您已经从 API 中获取了用户列表。如果你一次获取一个,你确实可以使用 redux thunk。我仍然建议将用户存储为列表,这样您就可以轻松地在它们之间切换。在这种情况下,你的 thunk 会想要从商店中获取用户(如果它存在),或者如果它不存在则获取它。像这样:
// Alternately, you could pass *no* argument, and grab currentUserId
// from state like users below
const getUser = userId => (dispatch, getState) => {
const localUsers = getState().users;
const localUser = localUsers.find(u => u.id === userId);
if (localUser) {
// Because the user is in the store, we just need to point the frontend
// to the right user.
dispatch(updateCurrentUserId(userId));
} else {
// Fetch the user, add them to the store, and then point to them.
fetch(`whatever.com/users/${userId}`)
.then(response => {
dispatch(addUser(response.data));
dispatch(updateCurrentUserId(userId));
}).catch(err => /* do something */);
}
}
此 thunk 允许您根据您的用户是否存在于数据中来有条件地和异步地运行。但是,与您的设计不同的是,您不会在新用户到来时覆盖当前用户。
请注意,您也可以在没有 currentUserId
的情况下执行此操作,而不是仅从 URL 解析用户 ID。