React应用页面加载后首次点击Remove按钮无响应问题排查
问题排查与解决方案
嘿,我来帮你拆解这个首次点击Remove按钮无效的诡异问题!
核心原因:异步操作未正确等待
你的handleRemove函数里,updateDisease是一个带async/await的异步函数,但你调用它的时候没有加await,导致fetchAndUpdate会在PUT请求还没完成、后端数据还没更新的时候就执行了。第一次点击时,fetch到的还是旧数据,所以页面没变化;第二次点击时,第一次的PUT请求已经完成,后端数据更新了,所以fetch能拿到新列表,页面就正常了。
另外还有几个小问题也需要修正:
handleKeep里的日志拼写错误:conaole.log应该是console.logcolumns的useMemo依赖中,handleRemove和handleKeep每次组件渲染都会重新创建,导致useMemo失效,columns会频繁重新生成,影响性能
修正后的代码方案
1. 修复异步等待逻辑
把handleRemove改成异步函数,等待updateDisease完成后再执行fetchAndUpdate:
const handleRemove = async (e) => { console.log("Remove!"); await updateDisease(e, 1); // 等待PUT请求完成后再获取新数据 fetchAndUpdate(); }
2. 修正handleKeep的拼写错误+补全异步等待
const handleKeep = async (e) => { console.log("Keep!"); // 修正拼写错误 await updateDisease(e, 0); // 这里也建议加await,避免后续扩展时出现同类异步问题 }
3. 优化函数稳定性,避免useMemo失效
用useCallback包裹handleRemove和handleKeep,让它们的引用保持稳定,这样columns的useMemo就能正常生效:
const handleRemove = useCallback(async (e) => { console.log("Remove!"); await updateDisease(e, 1); fetchAndUpdate(); }, [fetchAndUpdate, updateDisease]); const handleKeep = useCallback(async (e) => { console.log("Keep!"); await updateDisease(e, 0); }, [updateDisease]);
4. 修正columns的useMemo语法错误
你原来的代码里把handleRemove误写在了数组外面,修正后:
const columns = React.useMemo( () => [ { Header: 'Disease List', columns: [ { Header: 'ID', accessor: 'id' }, { Header: 'Remove/Keep', Cell: ({ row }) => ( <div> <Button onClick={() => handleRemove(row.original)}>Remove</Button> <Button onClick={() => handleKeep(row.original)}>Keep</Button> </div> ) } ] } ], [handleRemove, handleKeep] );
补充优化建议
updateDisease里直接修改传入的disease对象不是最佳实践,React状态更新依赖不可变数据,建议创建新对象再传给axios:
const updateDisease = async (disease, newIsRemovedVal) => { // 创建新对象,避免修改原状态数据 const updatedDisease = { ...disease, isRemoved: newIsRemovedVal }; await axios({ method: "PUT", url: `api/diseases/${disease.id}`, data: updatedDisease, // axios会自动序列化对象为JSON headers: { 'Content-Type': 'application/json; charset=utf-8' } }); };
内容的提问来源于stack exchange,提问作者SkyeBoniwell
相关产品推荐
相关产品推荐

