You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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">&times;</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">&times;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:37:37