React弹窗触发时调用GET请求加载任务详情的问题排查
嘿Paul,让我们一步步拆解你的问题,逐个解决:
1. 先搞定 no-unused-expressions 报错
这个错误通常是代码里出现了无意义的表达式,结合你的描述,大概率是这两个原因:
getTask调用的问题:你注释了match.params.id,但如果直接写getTask(match.params.id),要确保match参数正确传递,且在调用前判断ID是否存在(避免传undefined)。另外,别忘了把match.params.id加入useEffect的依赖数组,不然ID变化时不会重新拉取数据:useEffect(() => { // 确保有ID才调用接口 if (match.params.id) { getTask(match.params.id); } }, [getTask, match.params.id]); // 依赖数组要包含ID- JSX条件渲染的逻辑问题:你原来的
{(displayEdit && <TaskItem task={task} />) || (<div>{/* <TaskEdit /> */}</div>)}可以简化成更清晰的三元表达式,避免潜在的表达式解析错误:{displayEdit ? <TaskItem task={task} /> : <TaskEdit task={task} />}
2. 弹窗与路由的冲突问题
你参考的教程是用路由状态控制弹窗,但你现在混用了useModal的本地状态和路由,导致弹窗打开时路由没跳转到/taskedit/:id,自然拿不到ID。这里有两种解决方案:
方案一:完全用路由控制弹窗(贴合教程思路)
放弃useModal里的secondModalIsShowing状态,用路由跳转来触发弹窗:
- 点击编辑按钮时,用
history.push跳转到对应路由:// 父组件里的编辑按钮示例 <button onClick={() => history.push(`/taskedit/${task.id}`)}>编辑任务</button> - 修改
TaskModal,通过路由match.params.id获取ID,关闭弹窗时回退路由:const TaskModal = ({ getTask, task: { task, loading }, match, history }) => { const [displayEdit, toggleDisplayEdit] = useState(false); useEffect(() => { if (match.params.id) { getTask(match.params.id); } }, [getTask, match.params.id]); // 无ID时不渲染弹窗 if (!match.params.id) return null; return ReactDOM.createPortal( <React.Fragment> <div className="modal-overlay" /> <div className="modal-wrapper" aria-modal aria-hidden tabIndex={-1} role="dialog"> <div className="modal"> <div className="modal-header"> 编辑任务 <button type="button" className="modal-header__button" onClick={() => history.goBack()} aria-label="关闭" > <span aria-hidden="true">×</span> </button> </div> <div className="modal-body"> {loading ? ( <p>加载中...</p> ) : task ? ( <> <button onClick={() => toggleDisplayEdit(prev => !prev)}> {displayEdit ? '查看任务' : '编辑任务'} </button> {displayEdit ? <TaskEdit task={task} /> : <TaskItem task={task} />} </> ) : ( <p>未找到任务</p> )} </div> </div> </div> </React.Fragment>, document.body ); }; - 路由配置保持不变,把
TaskModal放在主路由外层即可。
方案二:保持本地状态,手动传递任务ID
如果你不想依赖路由,继续用useModal控制弹窗,那就修改Hook支持传递ID:
- 更新
useModal,增加存储任务ID的状态:import { useState } from "react"; const useModal = () => { const [isShowing, setIsShowing] = useState(false); const [secondModalState, setSecondModalState] = useState({ isShowing: false, taskId: null }); function toggle() { setIsShowing(!isShowing); } function secondToggle(taskId = null) { setSecondModalState(prev => ({ isShowing: !prev.isShowing, taskId: taskId !== null ? taskId : prev.taskId })); } return { isShowing, toggle, secondModalIsShowing: secondModalState.isShowing, secondModalTaskId: secondModalState.taskId, secondToggle, }; }; export default useModal; - 父组件点击编辑时传递ID:
<button onClick={() => secondToggle(task.id)}>编辑任务</button> - 修改
TaskModal,接收secondModalTaskId并拉取数据:const TaskModal = ({ getTask, task: { task, loading }, secondModalIsShowing, secondModalTaskId, hide }) => { const [displayEdit, toggleDisplayEdit] = useState(false); useEffect(() => { if (secondModalIsShowing && secondModalTaskId) { getTask(secondModalTaskId); } }, [getTask, secondModalIsShowing, secondModalTaskId]); if (!secondModalIsShowing) return null; return ReactDOM.createPortal( <React.Fragment> <div className="modal-overlay" /> <div className="modal-wrapper" aria-modal aria-hidden tabIndex={-1} role="dialog"> <div className="modal"> <div className="modal-header"> 编辑任务 <button type="button" className="modal-header__button" onClick={hide} aria-label="关闭" > <span aria-hidden="true">×</span> </button> </div> <div className="modal-body"> {loading ? ( <p>加载中...</p> ) : task ? ( <> <button onClick={() => toggleDisplayEdit(prev => !prev)}> {displayEdit ? '查看任务' : '编辑任务'} </button> {displayEdit ? <TaskEdit task={task} /> : <TaskItem task={task} />} </> ) : ( <p>未找到任务</p> )} </div> </div> </div> </React.Fragment>, document.body ); };
3. 最后几个细节提醒
- Redux连接检查:确保
TaskModal的mapStateToProps正确获取了task数据,比如:const mapStateToProps = state => ({ task: state.task // 和你的reducer key保持一致 }); export default connect(mapStateToProps, { getTask })(TaskModal); - Loading状态处理:一定要在数据加载完成前显示加载提示,避免渲染
undefined的task导致报错。
内容的提问来源于stack exchange,提问作者Paul Towers
相关产品推荐
相关产品推荐

