React - 使用 useLocation 根据 URL 显示特定内容

React - display specific content based on URL using useLocation

试图自学反应并卡在一个部分...我似乎无法根据 URL 使用 useLocation() 显示特定于页面的内容 -- 救命!

App.js - 路由器在点击时显示页面,耶!

    <Router>
        <Routes>
            <Route exact path="/" element={<Home />} />
            <Route path="/project/projectOne" element={<Project />} />
            <Route path="/project/projectTwo" element={<Project />} />
        </Routes>
    </Router>

Project.js - 项目模板按预期提供组件

const Project = () => {
return (
    <div className='content-wrapper'>
        <Scroll />
        <ProjectIntro />
        <ProjectContent />
        <ProjectGrid />
        <Contact />
    </div>
); }; export default Project;

ProjectIntro.js - 一个试图提供内容的组件——这就是我卡住的地方,useLocation() 看到了路径,但我不知道如何显示“projectIntroDetails”基于该路径。

const projectOne = () => {
  <h1 className='project-intro-heading'>Title Here</h1>,
  <figure className='project-intro-image'>
    <img src={projectImage} alt='placeholder'/>
  </figure> 
}

const projectTwo = () => {
    <h1 className='project-intro-heading'>Title Here</h1>,
    <figure className='project-intro-image'>
        <img src={projectTwoImage} alt='placeholder' />
    </figure>
}


const projectIntroDetails = {
    projectOne: {
        component: <projectOne />
    },
    projectTwo: {
        component: <projectTwo />
    }
}

const ProjectIntro = () => {
    const projectPath = useLocation();
    console.log(projectPath);

    // this is where I need help
    // how do I turn the path into seeing details to render the correct content?
    const projectIntroDetail = projectIntroDetails[projectPath.pathname.split("/project/")];

    return (
        <div className='project-intro'>
            {projectIntroDetail}
        </div>
    );

}; export default ProjectIntro;

您可以使用带有 switch 语句的组件来确定要呈现哪个子组件。此方法允许您将任何其他道具传递给子组件。

如果您不需要 <div className='project-intro'> 元素,您也可以直接在 ProjectIntro 组件内渲染开关。

const ProjectOne = () => {
  <h1 className='project-intro-heading'>Title Here</h1>,
  <figure className='project-intro-image'>
    <img src={projectImage} alt='placeholder'/>
  </figure> 
}

const ProjectTwo = () => {
    <h1 className='project-intro-heading'>Title Here</h1>,
    <figure className='project-intro-image'>
        <img src={projectTwoImage} alt='placeholder' />
    </figure>
}

const ProjectIntros = ({ slug, ...props }) => {
    switch(slug) {
        case 'projectOne':
            return <ProjectOne {...props} />;
        case 'projectTwo':
            return <ProjectTwo {...props} />;
        default:
            return null;
    }
}

const ProjectIntro = () => {
    const projectPath = useLocation();
    console.log(projectPath);

    return (
        <div className='project-intro'>
            <ProjectIntros slug={projectPath.pathname.split("/")[2]} />
        </div>
    );

}; export default ProjectIntro;

您真的不需要使用 useLocation 挂钩或 pathname 值来处理任何条件渲染逻辑,这就是路由组件的用途。

我建议将正确的 sub-project 组件作为道具传递到正确匹配的路线上,或者重构路线以更“反应路由器”的方式做到这一点。

将组件作为 prop 示例向下传递:

应用程序

<Router>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route
      path="/project/projectOne"
      element={<Project projectIntro={<ProjectOne />} />}
    />
    <Route
      path="/project/projectTwo"
      element={<Project projectIntro={<ProjectTwo />} />}
    />
  </Routes>
</Router>

项目

const Project = ({ projectIntro }) => {
  return (
    <div className='content-wrapper'>
      <Scroll />
      <div className='project-intro'>
        {projectIntro}
      </div>
      <ProjectContent />
      <ProjectGrid />
      <Contact />
    </div>
  );
};

充分利用 react-router-dom

项目

Project转换为布局组件,并在嵌套路由上渲染ProjectOneProjectTwo组件。布局路由旨在用于共享公共 UI 元素和布局,并将路由内容呈现到插座中。

import { Outlet } from 'react-router-dom';

const Project = () => {
  return (
    <div className='content-wrapper'>
      <Scroll />
      <div className='project-intro'>
        <Outlet /> // <-- render nested routes here
      </div>
      <ProjectContent />
      <ProjectGrid />
      <Contact />
    </div>
  );
};

应用程序

<Router>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/project" element={<Project />}>
      <Route path="projectOne" element={<ProjectOne />} />
      <Route path="projectTwo" element={<ProjectTwo />} />
    </Route>
  </Routes>
</Router>