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

useEffect未随URL变更获取数据问题求助

问题描述

我配置了两个路由:

  • localhost:3000/content
  • localhost:3000/content/<projectId>

路由代码如下:

<Route
  path="/content"
  element={
    <RequireAuth>
      <ContentPage />
    </RequireAuth>
  }
/>

<Route
  path="/content/:projectId"
  element={
    <RequireAuth>
      <ProjectPage />
    </RequireAuth>
  }
/>

顺序导航时功能正常,但跳转至其他页面再返回后,/content/:projectId页面的博客文章无法加载;直接刷新或访问该URL时,仅显示项目名,页面数据加载失败。

ProjectPage核心代码如下:

import React, { useEffect, useState } from "react";
import { useLocation, useSearchParams, useParams } from "react-router-dom";

const ProjectPage = () => {
  const { projectId } = useParams();
  const [pagesname, setPagesname] = useState([]);
  const [dashboarderror, setDashboarderror] = useState();
  const location = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const pageId = searchParams.get("pageId");

  useEffect(() => {
    async function fetchData() {
      try {
        const authconfig = {
          headers: {
            "Content-Type": "application/json",
            Authorization:
              "Bearer " + JSON.parse(localStorage.getItem("user_token")).token,
          },
        };
        const res = await axios.get(
          dashboardURL,
          authconfig
        );
        for (let i = 0; i < res.data.matrixDetails[2].projects.length; i++) {
          if (
            res.data.matrixDetails[2].projects[i].projectTypeName ===
            location.state
          ) {
            setPagesname(res.data.matrixDetails[2].projects[i].pages);
          }
        }
      } catch (e) {
        setDashboarderror(e);
      }
    }
    fetchData();
  }, [location]);    // location可用但useEffect未随URL变更触发

  return (
    <Box>
      {pagesname.map((sname) => {
        return (
          <div key={sname.pageKeyId}>
            <Button
              style={{
                textTransform: "none",
                color: "#546e7a",
                backgroundColor: "transparent",
                padding: "2px",
              }}
              onClick={() =>
                setSearchParams({ pageId: sname.pageKeyId })
              }
            >
              <DataTreeView
                treeItems={pagesname}
                pgCode={sname.pageKeyId}
              />
            </Button>
          </div>
        );
      })}
      {pageId && <PageView pageId={pageId} />}
    </Box>
  )
}

问题核心:依赖location的useEffect未在URL变更时触发,且直接访问/刷新页面时location.state丢失,导致无法匹配对应项目的页面数据。


解决方案

1. 修正useEffect依赖项

location对象的引用在URL参数变化时可能不会更新,无法触发useEffect。将URL动态参数projectId加入依赖数组,确保projectId变化时重新获取数据:

useEffect(() => {
  async function fetchData() {
    // ... 原有请求逻辑
  }
  fetchData();
}, [projectId]); // 替换为projectId作为依赖

2. 替换不可靠的location.state匹配逻辑

location.state仅在通过navigate方法传递state时存在,直接访问或刷新页面时会丢失。改用URL中的projectId关联后端数据:

假设后端返回的项目包含与URL参数一致的projectId字段,修改匹配逻辑:

for (let i = 0; i < res.data.matrixDetails[2].projects.length; i++) {
  if (res.data.matrixDetails[2].projects[i].projectId === projectId) {
    setPagesname(res.data.matrixDetails[2].projects[i].pages);
    break; // 找到匹配项后退出循环,提升性能
  }
}

如果后端用projectTypeName作为标识,且projectId等于projectTypeName,则直接替换:

if (res.data.matrixDetails[2].projects[i].projectTypeName === projectId) {
  setPagesname(res.data.matrixDetails[2].projects[i].pages);
  break;
}

3. 优化后端请求(可选)

当前前端循环所有项目匹配效率较低,若后端支持,可直接根据projectId请求对应项目数据:

const res = await axios.get(
  `${dashboardURL}/projects/${projectId}`, // 假设后端提供该接口
  authconfig
);
setPagesname(res.data.pages); // 直接设置返回的页面数据

4. 处理location.state丢失的边界情况

若必须依赖location.state,可在页面加载时检查其是否存在,不存在则从localStorage读取已存储的项目名:

import { useNavigate } from "react-router-dom";

const ProjectPage = () => {
  const navigate = useNavigate();
  // ... 其他代码

  useEffect(() => {
    async function fetchData() {
      try {
        const projectName = location.state || localStorage.getItem("currentProjectName");
        if (!projectName) {
          navigate("/content"); // 无项目名时跳转至content页面
          return;
        }
        // ... 用projectName执行后续匹配逻辑
      } catch (e) {
        setDashboarderror(e);
      }
    }
    fetchData();
  }, [projectId, location.state, navigate]);
}

内容的提问来源于stack exchange,提问作者Udayendu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:05:00