嵌套减速器
Nested reducers
为了学习 Redux,我开始了一个简单的 Web 应用程序。
如果有 "authentification" 操作验证用户名和密码。然后我想要调用 "login" 或 "fail" 操作。我无法弄清楚如何。
我可以调用身份验证步骤,但 nested/following 调用未执行。
如何从另一个函数中调用一个函数? (这就是我的问题令人沮丧的原因^^)
我的代码如下所示:
function authenticateClient(state, client){
if (client.password === 'perfectsec')
return dispatch(Actions.connectClient(client));
else
return dispatch(Actions.refuseClient(client));
}
在 reducer 中调用 dispatch 是不正确的。最简单的方法是直接调用函数 connectClient(state, client)
或 refuseClient(state, client)
。但是这一步并没有经过 redux 流程。
上下文代码:
/* actions.js */
export function authenticateClient(client) {
return { type: Types.authenticateClient, client };
}
export function connectClient(client, isNew) {
return { type: Types.connectClient, client, isNew };
}
export function refuseClient(client) {
return { type: Types.refuseClient, client };
}
/* main.js */
/* reducer */
const reducer = (state = loadState(), action) => {
console.log(chalk.red(`*${action.type}*`));
switch (action.type) {
case Actions.Types.authenticateClient:
return authenticateClient(state, action);
case Actions.Types.connectClient:
return connectClient(state, action);
case Actions.Types.refuseClient:
return refuseClient(state, action);
default:
return state;
}
};
/* store */
store = createStore(reducer);
/* app */
store.dispatch(Actions.authenticateClient({username, password}));
Reducer 不应该分派动作,或者做任何其他有副作用的事情。所有 reducer 都应该是状态和动作的纯函数(有效 state + action = newState
)——整个 Redux 库都是围绕这个假设构建的,我相信它是专门设计用来在你尝试在内部调用 dispatch 时抛出错误的一个减速器。
有条件地分派操作的最佳方法是创建一个新的 'action creator' - 您的应用程序中已经有一些这样的操作:
export function authenticateClient(client) {
return { type: Types.authenticateClient, client };
}
export function connectClient(client, isNew) {
return { type: Types.connectClient, client, isNew };
}
export function refuseClient(client) {
return { type: Types.refuseClient, client };
}
请注意,标准操作创建者不会自行发送操作。它们只是 return 一个动作的函数,你可以在某个时候自己调度(如果你想创建一个动作并坚持一段时间,这很方便在实际发送前不久)。一旦您开始编写异步动作创建器,水域就会变得有些混乱,但这并不真正在您的问题范围内,所以我现在将跳过它(不过,我建议阅读文档的异步部分!您可以做一些真正的一旦你开始思考它就会很酷。
你在这里试图表达的是一个函数,表示 'if a condition is true, give me a connectClient
action, if not, give me a refuseClient
action'。我们已经知道给你一个动作的函数是一个动作创建者,这让我们明白了这个答案的要点:动作创建者可以有逻辑。虽然他们中的 90% 只会接收数据并立即 return 一个对象,但这并不是他们可以采用的唯一形式。下面是如何表示此功能的示例:
export function connectClientIfValid(client) {
if (client.valid === true) {
return connectClient(client);
}
else {
return refuseClient(client);
}
}
同样,这个函数实际上没有派发任何东西 - 它只是 return 一个动作,您可以在闲暇时派发,就像这样:
dispatch(connectClientIfValid(client));
您的逻辑运行,并分派适当的操作,而不必损害减速器的 pure/synchronous 性质。您的减速器所要做的就是在动作进入时读取它们,并适当地更新状态——它不必关心导致动作发生的逻辑。
为了学习 Redux,我开始了一个简单的 Web 应用程序。
如果有 "authentification" 操作验证用户名和密码。然后我想要调用 "login" 或 "fail" 操作。我无法弄清楚如何。 我可以调用身份验证步骤,但 nested/following 调用未执行。
如何从另一个函数中调用一个函数? (这就是我的问题令人沮丧的原因^^)
我的代码如下所示:
function authenticateClient(state, client){
if (client.password === 'perfectsec')
return dispatch(Actions.connectClient(client));
else
return dispatch(Actions.refuseClient(client));
}
在 reducer 中调用 dispatch 是不正确的。最简单的方法是直接调用函数 connectClient(state, client)
或 refuseClient(state, client)
。但是这一步并没有经过 redux 流程。
上下文代码:
/* actions.js */
export function authenticateClient(client) {
return { type: Types.authenticateClient, client };
}
export function connectClient(client, isNew) {
return { type: Types.connectClient, client, isNew };
}
export function refuseClient(client) {
return { type: Types.refuseClient, client };
}
/* main.js */
/* reducer */
const reducer = (state = loadState(), action) => {
console.log(chalk.red(`*${action.type}*`));
switch (action.type) {
case Actions.Types.authenticateClient:
return authenticateClient(state, action);
case Actions.Types.connectClient:
return connectClient(state, action);
case Actions.Types.refuseClient:
return refuseClient(state, action);
default:
return state;
}
};
/* store */
store = createStore(reducer);
/* app */
store.dispatch(Actions.authenticateClient({username, password}));
Reducer 不应该分派动作,或者做任何其他有副作用的事情。所有 reducer 都应该是状态和动作的纯函数(有效 state + action = newState
)——整个 Redux 库都是围绕这个假设构建的,我相信它是专门设计用来在你尝试在内部调用 dispatch 时抛出错误的一个减速器。
有条件地分派操作的最佳方法是创建一个新的 'action creator' - 您的应用程序中已经有一些这样的操作:
export function authenticateClient(client) {
return { type: Types.authenticateClient, client };
}
export function connectClient(client, isNew) {
return { type: Types.connectClient, client, isNew };
}
export function refuseClient(client) {
return { type: Types.refuseClient, client };
}
请注意,标准操作创建者不会自行发送操作。它们只是 return 一个动作的函数,你可以在某个时候自己调度(如果你想创建一个动作并坚持一段时间,这很方便在实际发送前不久)。一旦您开始编写异步动作创建器,水域就会变得有些混乱,但这并不真正在您的问题范围内,所以我现在将跳过它(不过,我建议阅读文档的异步部分!您可以做一些真正的一旦你开始思考它就会很酷。
你在这里试图表达的是一个函数,表示 'if a condition is true, give me a connectClient
action, if not, give me a refuseClient
action'。我们已经知道给你一个动作的函数是一个动作创建者,这让我们明白了这个答案的要点:动作创建者可以有逻辑。虽然他们中的 90% 只会接收数据并立即 return 一个对象,但这并不是他们可以采用的唯一形式。下面是如何表示此功能的示例:
export function connectClientIfValid(client) {
if (client.valid === true) {
return connectClient(client);
}
else {
return refuseClient(client);
}
}
同样,这个函数实际上没有派发任何东西 - 它只是 return 一个动作,您可以在闲暇时派发,就像这样:
dispatch(connectClientIfValid(client));
您的逻辑运行,并分派适当的操作,而不必损害减速器的 pure/synchronous 性质。您的减速器所要做的就是在动作进入时读取它们,并适当地更新状态——它不必关心导致动作发生的逻辑。