React兄弟组件通过Context传值首次打开Modal时currentId为null如何解决
问题根因
你遇到的问题本质是React状态更新的异步批量执行特性:
- 同一个同步函数内调用的多次
setState会被合并批量处理,直到整个函数执行完才会触发重渲染,所以你在handleModalOpen里先更新id再打开Modal,Modal第一次渲染时拿到的还是更新前的null值 - 补充代码里
checkForIdUpdate调用setTask也是异步操作,调用完直接发起axios请求用的task还是更新前的旧值,所以就算条件触发也达不到预期效果
小提示:你之前在CardBoard里写的useEffect依赖项是
handleModalOpen,属于错误写法,这个函数的引用默认不会变化,只有组件首次渲染会执行一次,要监听currentCardBoardId的变化的话,应该把依赖项改为[currentCardBoardId]。
可行解决方案
方案1:调整Modal打开的触发时机
把打开Modal的逻辑绑定到id的更新回调上,确保id更新完成后再打开Modal:
// 原来的handleModalOpen改成仅更新id const handleModalOpen = () => { setCurrentCardBoardId(id); }; // 新增useEffect监听id变化,确认id更新后再打开Modal useEffect(() => { if(currentCardBoardId !== null) { setShowModal(true); } }, [currentCardBoardId]) // 关闭Modal时同步重置id,避免下次打开出现旧值干扰 const handleModalClose = () => { setShowModal(false); setCurrentCardBoardId(null); }
方案2:Modal组件内监听id更新同步状态
如果不想调整外层触发逻辑,可以直接在Modal组件内监听context传入的id,同步更新内部的task状态:
// ModalWindow组件内新增useEffect const {currentCardBoardId} = useContext(settingsModalContext); useEffect(() => { if(currentCardBoardId !== null) { setTask(prev => ({...prev, cardBoardId: currentCardBoardId})) } }, [currentCardBoardId])
方案3:修复提交逻辑的异步问题
不需要依赖setTask的异步更新结果,直接拼接最终提交的参数即可:
const handleSubmit = async (e) => { setShowModal(false); setRefreshAlertOpen(true); try { // 直接拼接最终提交的参数,跳过setTask的异步等待 const submitTask = currentCardBoardId ? {...task, cardBoardId: currentCardBoardId} : task; const newTask = await axios.post("http://localhost:5000/taskData", submitTask); console.log(newTask); } catch (error) { console.log(error); } };
内容的提问来源于stack exchange,提问作者Dalibor_1408
相关产品推荐
相关产品推荐

