reactjs 动态React路线

yqhsw0fo  于 2022-11-29  发布在  React
关注(0)|答案(4)|浏览(275)

我目前正在学习动态响应路由。在我的示例代码中,我为每个工作设置了不同的按钮。当单击按钮时,它必须呈现WorkDetails组件。然而,即使我手动更改URL slug,它也不会这样做。我很难找出哪里出了问题。
代码和框:https://codesandbox.io/s/dynamic-routes-budulp?file=/src/App.js
这是我的应用程序组件中的路线

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/works" element={<Work data={data} />}>
      <Route path=":slug" element={<WorkDetails />} />
    </Route>
  </Routes>
</BrowserRouter>

在我的Work组件中,每个按钮都用Link包围。对于路径,我使用了数据文件中对象数组中的slug

const Work = ({ data }) => {
  return (
    <div>
      <h1>Works</h1>
      {data.map(({ id, name, slug }) => {
        return (
          <div key={id} id={id}>
            <h2>{name}</h2>
            <Link to={slug}>
              <button>Work Details</button>
            </Link>
          </div>
        );
      })}
    </div>
  );
};

data.js

let works = [
  {
    id: 1,
    name: "Work 1",
    slug: "work-one",
    subtopics: [
      {
        title: "About the project",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Process",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Result",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      }
    ]
  },
  {
    id: 2,
    name: "Work 2",
    slug: "work-two",
    subtopics: [
      {
        title: "About the project",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Process",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Result",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      }
    ]
  },
  {
    id: 3,
    name: "Work 3",
    slug: "work-three",
    subtopics: [
      {
        title: "About the project",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Process",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Result",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      }
    ]
  },
  {
    id: 4,
    name: "Work 4",
    slug: "work-four",
    subtopics: [
      {
        title: "About the project",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Process",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      },
      {
        title: "Result",
        description:
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Sagittis orci a scelerisque purus semper eget duis at. Sodales neque sodales ut etiam sit amet. Proin sed libero enim sed faucibus turpis in eu mi. Blandit libero volutpat sed cras ornare arcu dui. Urna nunc id cursus metus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Curabitur gravida arcu ac tortor. Natoque penatibus et magnis dis parturient montes nascetur. Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Aenean sed adipiscing diam donec adipiscing."
      }
    ]
  }
];

在我的WorkDetails组件上,我使用了useParams(),我希望它返回slug。然后,我使用slug查找具有相同slug的对象。然后,状态将用找到的对象更新。

const WorkDetails = () => {
  const { slug } = useParams();

  // Find the object with the same slug as the params.
  const [work, setWork] = useState(null);
  let findWork = data.find((d) => d.slug === slug);
  if (findWork) {
    setWork(findWork);
  }

  return (
    <div>
      <Link to="/works">
        <button>Back to Works</button>
      </Link>
      <h1>{work.name}</h1>
      {work.subtopic.map((topic) => {
        return (
          <>
            <h2>{topic.title}</h2>
            <p>{topic.description}</p>
          </>
        );
      })}
    </div>
  );
};
00jrzges

00jrzges1#

将app.js中的代码更改为

<BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/works" element={<Work data={data} />} />
        <Route path="/works/:slug" element={<WorkDetails />} />
      </Routes>
    </BrowserRouter>

以及这条线<Link to={slug}>到这条线<Link to={ ${slug} }>
和工作细节

import { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import data from "./data";

const WorkDetails = () => {
  const { slug } = useParams();
  console.log(";", slug);

  // Find the object with the same slug as the params.
  const [work, setWork] = useState({});
  let findWork = data.find((d) => d.slug === slug);
  console.log("ll", findWork);
  
  useEffect(()=>{
    if (findWork) {
      setWork(findWork);
    }

  }, [findWork])
  return (
    <div>
      <Link to="/works">
        <button>Back to Works</button>
      </Link>
      <h1>{work?.name}</h1>
      {work?.subtopics?.map((topic) => {
        return (
          <>
            <h2>{topic.title}</h2>
            <p>{topic.description}</p>
          </>
        );
      })}
    </div>
  );
};

export default WorkDetails;
lmyy7pcs

lmyy7pcs2#

将工作详细信息文件更改为

const WorkDetails = () => {
  const { slug } = useParams();
  // Find the object with the same slug as the params.
  const [work, setWork] = useState({});

  useEffect(()=>{
  let findWork = data.find((d) => d.slug === slug);
    if (findWork) {
      setWork(findWork);
    }
  }, [findWork])

  return (
    <div>
      <Link to="/works">
        <button>Back to Works</button>
      </Link>
      <h1>{work.name}</h1>
      {work.subtopic?.map((topic) => {
        return (
          <>
            <h2>{topic.title}</h2>
            <p>{topic.description}</p>
          </>
        );
      })}
    </div>
  );
};
ruyhziif

ruyhziif3#

有几个问题:
1.路由的顺序不正确,应该是从特定到一般。
1.此外,在工作详细信息中,您设置的变量不正确。
我已经为你调整了你的例子,见下文。
https://codesandbox.io/s/dynamic-routes-forked-7j026p

qyzbxkaa

qyzbxkaa4#

个问题

WorkDetails组件呈现在***嵌套***路由上,因此为了呈现在"/works"上呈现的父Work组件,必须为嵌套路由呈现Outlet组件,以便将其element内容呈现到其中。
另一个问题是,WorkDetails发布状态更新是无意的副作用。事实上,work状态是完全不必要的,因为它能够从当前slug路由路径参数值和工作项的data数组中派生。它是一个将派生的“状态”存储在React状态中的React反模式。Filter/从data数组中找到匹配的工作项,如果需要,通过useMemo挂接记住该值,而不是存储在任何状态中。

溶液

布局嵌套路线(& N)

如果要使用Work作为布局路线,则还应呈现Outlet组件,以便嵌套路线将其内容呈现到其中。
示例:
第一个

常规路线

如果您想将WorkWorkDetails呈现为两个单独的路由和组件,则可以取消嵌套路由。呈现WorkDetails不需要Outlet组件。
示例:

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/works">
      <Route index element={<Work />} />               // <-- "/works"
      <Route path=":slug" element={<WorkDetails />} /> // <-- "/works/:slug"
    </Route>
  </Routes>
</BrowserRouter>

WorkDetails应计算并呈现派生的“状态”

WorkDetails组件不应将派生的工作项值存储到本地状态中,而应直接计算并呈现搜索结果。
示例:

const WorkDetails = () => {
  const { slug } = useParams();

  // Find the object with the same slug as the params.
  const findWork = data.find((d) => d.slug === slug);

  if (!findWork) {
    return null; // <-- or some "Not Found" fallback UI
  }

  return (
    <div>
      <Link to="/works">
        <button>Back to Works</button>
      </Link>
      <h1>{work.name}</h1>
      {work.subtopic.map((topic) => {
        return (
          <React.Fragment key={topic.title}> // <-- don't forget React key
            <h2>{topic.title}</h2>
            <p>{topic.description}</p>
          </React.Fragment>
        );
      })}
    </div>
  );
};

如果需要记忆派生状态,则使用useMemo挂接:

const findWork = useMemo(() => data.find((d) => d.slug === slug), [slug]);

相关问题