Body:我正在开发一个 MERN stack todo 应用程序,并面临一个问题,即新添加的待办事项不会立即出现在 UI 中。新的待办事项仅在我刷新页面后才会显示。
通过单击“添加”按钮添加新的待办事项后,除非我手动刷新页面,否则该待办事项不会出现在 UI 中。我正在使用
setTodos
更新 TodoContext
中的状态,但新添加的待办事项不会立即反映在 UI 中。
我希望新添加的待办事项在单击“添加”按钮后立即显示在 UI 中,而不需要刷新页面。
const TodoContext = createContext();
export const TodoProvider = ({ children }) => {
const [todos, setTodos] = useState([]);
const addTodos = async (title) => {
try {
const response = await axios.post('/api/todos/addTodo', { title });
// Updating the state with the newly added todo
setTodos((prev) => [...prev, response.data.data]);
} catch (error) {
console.error(error);
}
};
return (
<TodoContext.Provider value={{ todos, addTodos }}>
{children}
</TodoContext.Provider>
);
};
const Add = () => {
const { addTodos } = useTodo();
const [input, setInput] = useState("");
const handleAdd = async () => {
if (input.trim()) {
await addTodos(input); // Adding new todo
setInput(""); // Resetting input field
}
};
return <button onClick={handleAdd}>Add</button>;
};
const Read = () => {
const { todos } = useTodo();
return (
<div>
{todos.map(todo => (
<div key={todo._id}>{todo.title}</div> // Displaying todos
))}
</div>
);
};
出现此行为的原因是您使用 setTodos 进行的状态更新没有立即反映在 UI 中。这是因为 React 的状态更新是异步的,并且 UI 重新渲染发生在状态更新之后。 要解决此问题并使新添加的待办事项立即出现在 UI 中,您可以使用以下方法:
乐观的用户界面更新: 您可以乐观地更新状态,即在用户单击“添加”按钮后立即更新状态,而不是等待 API 响应来更新状态。这将使新的待办事项立即出现在 UI 中,然后您可以使用 API 响应中的实际数据更新状态。
const TodoContext = createContext();
export const TodoProvider = ({ children }) => {
const [todos, setTodos] = useState([]);
const addTodos = async (title) => {
try {
setTodos((prev) => [...prev, { _id: Math.random().toString(), title, completed: false }]);
const response = await axios.post('/api/todos/addTodo', { title });
// update with actual one
setTodos((prev) =>
prev.map((todo) =>
todo._id === response.data.data._id ? response.data.data : todo
)
);
} catch (error) {
console.error(error);
// revert the change if it fails
setTodos((prev) => prev.filter((todo) => todo._id !== response.data.data._id));
}
};
return (
<TodoContext.Provider value={{ todos, addTodos }}>
{children}
</TodoContext.Provider>
);
};
const Add = () => {
const { addTodos } = useTodo();
const [input, setInput] = useState("");
const handleAdd = async () => {
if (input.trim()) {
await addTodos(input);
setInput("");
}
};
return <button onClick={handleAdd}>Add</button>;
};
const Read = () => {
const { todos } = useTodo();
return (
<div>
{todos.map((todo) => (
<div key={todo._id}>{todo.title}</div>
))}
</div>
);
};