如何实现React两个组件中公共组件的同步删除?
React组件任务同步删除问题解决方案
问题
有两个React组件TaskLists和Daycard,均使用公共组件TaskCard展示任务。在其中一个组件内调用API删除任务后,另一个组件中的对应TaskCard不会立即消失,需刷新浏览器才会移除。
原因
两个组件各自维护独立的tasks状态,删除操作仅更新了当前组件的本地状态,另一个组件的状态仍为旧数据,导致界面不同步。
解决方案
方案一:状态提升至共同父组件
将任务状态和删除逻辑提取到两个组件的共同父组件中,通过props传递给子组件,确保状态更新能同步到所有使用该状态的组件。
父组件示例(如App.js)
import React, { useEffect, useState } from "react"; import { getTasks, deleteTask } from "../api/task.api"; import { TaskLists } from "./TaskLists"; import { Daycard } from "./Daycard"; function App() { const [tasks, setTasks] = useState([]); // 初始化加载任务 useEffect(() => { async function loadTasks() { const res = await getTasks(); setTasks(res.data); } loadTasks(); }, []); // 统一删除逻辑:先调用API,再更新状态 const removeTask = async (id) => { await deleteTask(id); setTasks(tasks.filter(task => task.id !== id)); }; return ( <div> <TaskLists tasks={tasks} onDelete={removeTask} /> <Daycard hashv="your-hash-value" tasks={tasks} onDelete={removeTask} /> </div> ); } export default App;
改造TaskLists组件
import React from "react"; import { TaskCard } from "./TaskCard"; export function TaskLists({ tasks, onDelete }) { return ( <div> {tasks.map((task) => ( <TaskCard key={task.id} task={task} onDelete={onDelete} /> ))} </div> ); }
改造Daycard组件
import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import { TaskCard } from "./TaskCard"; export function Daycard({ hashv, tasks, onDelete }) { let b = 0; const [hash, setHash] = useState(hashv); const navigate = useNavigate(); const handleClick = () => { if (b === 0) { navigate(`/tasks-create?hash=${hash}`); console.log(`the hash is ${hash}`); } }; return ( <div onClick={handleClick} className="col pb-5 bg-light border border-dark flex-grow-1" style={{ height: "auto" }} > {tasks.map((task) => { if (task.hash == hash) { b = 1; return <TaskCard key={task.id} task={task} onDelete={onDelete} />; } })} </div> ); }
方案二:使用React Context全局管理状态
若组件层级较深,状态提升不便,可通过Context全局共享任务状态和删除方法。
创建TaskContext.js
import React, { createContext, useContext, useEffect, useState } from "react"; import { getTasks, deleteTask } from "../api/task.api"; const TaskContext = createContext(); // 全局状态提供者 export function TaskProvider({ children }) { const [tasks, setTasks] = useState([]); useEffect(() => { async function loadTasks() { const res = await getTasks(); setTasks(res.data); } loadTasks(); }, []); const removeTask = async (id) => { await deleteTask(id); setTasks(tasks.filter(task => task.id !== id)); }; return ( <TaskContext.Provider value={{ tasks, removeTask }}> {children} </TaskContext.Provider> ); } // 自定义hooks,简化Context调用 export function useTasks() { return useContext(TaskContext); }
根组件包裹Provider
import { TaskProvider } from "./TaskContext"; import { TaskLists } from "./TaskLists"; import { Daycard } from "./Daycard"; function App() { return ( <TaskProvider> <TaskLists /> <Daycard hashv="your-hash-value" /> </TaskProvider> ); } export default App;
改造TaskLists组件
import React from "react"; import { useTasks } from "./TaskContext"; import { TaskCard } from "./TaskCard"; export function TaskLists() { const { tasks, removeTask } = useTasks(); return ( <div> {tasks.map((task) => ( <TaskCard key={task.id} task={task} onDelete={removeTask} /> ))} </div> ); }
改造Daycard组件
import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import { useTasks } from "./TaskContext"; import { TaskCard } from "./TaskCard"; export function Daycard({ hashv }) { let b = 0; const [hash, setHash] = useState(hashv); const navigate = useNavigate(); const { tasks, removeTask } = useTasks(); const handleClick = () => { if (b === 0) { navigate(`/tasks-create?hash=${hash}`); console.log(`the hash is ${hash}`); } }; return ( <div onClick={handleClick} className="col pb-5 bg-light border border-dark flex-grow-1" style={{ height: "auto" }} > {tasks.map((task) => { if (task.hash == hash) { b = 1; return <TaskCard key={task.id} task={task} onDelete={removeTask} />; } })} </div> ); }
方案三:删除后重新拉取数据(简单但效率较低)
在每个组件的删除方法中,调用删除API成功后,重新拉取最新任务列表更新本地状态。
改造TaskLists的removeTask
const removeTask = async (id) => { await deleteTask(id); // 确保API调用成功 const res = await getTasks(); setTasks(res.data); };
改造Daycard的removeTask
const removeTask = async (id) => { await deleteTask(id); const res = await getTasks(); setTasks(res.data); };
注意:无论采用哪种方案,都要保证先成功调用删除API,再更新本地状态,避免出现本地状态与后端数据不一致的情况。
内容的提问来源于stack exchange,提问作者MrJonesBones
相关产品推荐
相关产品推荐

