【发布时间】:2022-01-07 16:03:54
【问题描述】:
我有两个减速器动作,我想一个接一个地调度。第一个修改状态,然后第二个使用修改后的状态的一部分进行另一次修改。困难在于,当调用第二次调度时,它仍然具有旧的过时状态,因此无法正确更新状态。
下面是一个示例(也可以在此处找到 - https://codesandbox.io/s/react-usereducer-hqtc2),其中有一个对话列表以及一个被视为“活动”对话的注释:
import React, { useReducer } from "react";
const reducer = (state, action) => {
switch (action.type) {
case "removeConversation":
return {
...state,
conversations: state.conversations.filter(
c => c.title !== action.payload
)
};
case "setActive":
return {
...state,
activeConversation: action.payload
};
default:
return state;
}
};
export default function Conversations() {
const [{ conversations, activeConversation }, dispatch] = useReducer(
reducer,
{
conversations: [
{ title: "James" },
{ title: "John" },
{ title: "Mindy" }
],
activeConversation: { title: "James" }
}
);
function removeConversation() {
dispatch({ type: "removeConversation", payload: activeConversation.title });
dispatch({ type: "setActive", payload: conversations[0] });
}
return (
<div>
Active conversation: {activeConversation.title}
<button onClick={removeConversation}>Remove</button>
<ul>
{conversations.map(conversation => (
<li key={conversation.title}>{conversation.title}</li>
))}
</ul>
</div>
);
}
在这里,当我单击“删除对话”按钮时,我想删除活动对话,然后将活动对话设置为列表顶部的那个。然而,在这里,当第一个调度从列表中删除对话时,第二个调度将 active 设置为conversations[0],它仍然包含删除的值(因为状态尚未更新)。因此,即使它已从列表中删除,它也会将活动对话保持在之前的状态。
我可能可以将逻辑组合成一个动作并在那里完成所有操作(删除对话并将所有设置为活动状态),但我希望尽可能让我的 reducer 动作各有一个责任。
有什么办法可以让第二个 dispatch call 有最新版本的状态,这样就不会出现这种问题了?
【问题讨论】:
标签: react-hooks