React类组件状态处理逻辑迁移为Hooks写法报错如何解决?
问题原因和修复方案
核心错误点:setTasks回调的参数取值错误
你在类组件中的state是外层包含tasks属性的对象,所以类组件setState回调拿到的prevState是整个状态对象,可以正确解构出tasks。
但在Hooks写法中,你用useState存的直接就是tasks分组对象本身,没有外层包装。你写的setTasks(({ tasks }) => {})相当于从prevState里解构tasks属性,而prevState本身就是你要的tasks集合,自然拿不到值,tasks变成undefined,后续调用tasks[item.status]就触发了类型错误。
额外隐患:直接修改原state对象
你之前的写法是直接对原state数组执行push操作,属于直接修改state的突变操作,不符合React状态不可变的更新原则,容易引发渲染异常,类组件写法虽然暂时运行正常,但也存在相同隐患。
修正后的代码
const [tasks, setTasks] = useState({ workingProgress: [], toDo: [], done: [], }); const history = useHistory(); useEffect(() => { TasksAPI.getAll().then((res) => { setTasks(prevTasks => { // 先拷贝原对象,避免修改原state const newTasks = { workingProgress: [...prevTasks.workingProgress], toDo: [...prevTasks.toDo], done: [...prevTasks.done], }; res.forEach((item) => { if (newTasks[item.status]) { newTasks[item.status].push(item); } }); return newTasks; }); }); }, []);
你也可以用更简洁的分组写法实现同样效果:
useEffect(() => { TasksAPI.getAll().then((res) => { setTasks(prev => { const result = { ...prev }; res.forEach(item => { if(result[item.status]) { result[item.status] = [...result[item.status], item]; } }); return result; }) }) }, [])
渲染逻辑说明
你的现有渲染代码不需要修改,Hooks中定义的tasks本身就是你要遍历的分组对象,和原来类组件中this.state.tasks结构完全一致。
内容的提问来源于stack exchange,提问作者Iván
相关产品推荐
相关产品推荐

