Home > front end >  Sub page navigation within React
Sub page navigation within React

Time:08-08

I'm new to React and I am trying to create sub navigation that will navigate between my project pages (post pages similar to Wordpress) when the user clicks a forward or back button. I think the functionality would need to update the URL to the id I have set in my data.js file.

Would I use a React state hook to achieve this functionality or is there a better way? I hope this makes sense and thanks in advance for any help you all can provide.

App.js file:

import { BrowserRouter, Routes, Route } from "react-router-dom";
import "./App.scss";

import About from "./pages/About";
import Error from "./pages/Error";
import Home from "./pages/Home";
import Layout from "./pages/Layout";
import Projects from "./pages/Projects";
import SingleProject from "./pages/SingleProject";
import SingleProjectLayout from "./pages/SingleProjectLayout";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />} />
          <Route path="about" element={<About />} />

          <Route path="projects" element={<SingleProjectLayout />}>
            <Route index element={<Projects />} />
            <Route path=":projectId" element={<SingleProject />} />
          </Route>

          <Route path="*" element={<Error />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default App;

data.js file:

const projects = [
  {
    id: "susie",
    name: "Susie",
    image: "https://placedog.net/800/640?id=32",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "jimmy",
    name: "Jimmy",
    image: "https://placedog.net/800/640?id=100",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "hank",
    name: "Hank",
    image: "https://placedog.net/800/640?id=69",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "bosley",
    name: "Bosley",
    image: "https://placedog.net/800/640?id=21",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "frank",
    name: "Frank",
    image: "https://placedog.net/800/640?id=22",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "gloria",
    name: "Gloria",
    image: "https://placedog.net/800/640?id=24",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "robbie",
    name: "Robbie",
    image: "https://placedog.net/800/640?id=60",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "lonnie",
    name: "Lonnie",
    image: "https://placedog.net/800/640?id=62",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
  {
    id: "lady",
    name: "Lady",
    image: "https://placedog.net/800/640?id=54",
    content: (
      <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Esse magnam veniam harum at qui quisquam impedit tempore reprehenderit! Ratione exercitationem reprehenderit vero! Voluptatem explicabo exercitationem alias iure eos harum non.</span>
    ),
    projectURL: "https://placedog.net/",
  },
];

export default projects;

SingleProjects.js

// import React, { useState, useEffect } from "react";

import { useParams } from "react-router-dom";
import projects from "../data";
import PageTitle from "../components/PageTitle";
import { LinkContainer } from "react-router-bootstrap";
import Button from "react-bootstrap/Button";
import { FaLink, FaAngleLeft } from "react-icons/fa";
import { Animated } from "react-animated-css";

function SingleProject() {
  const { projectId } = useParams();
  const project = projects.find((project) => project.id === projectId);
  const { image, name, content, projectURL } = project;

  return (
    <>
      <PageTitle title={name} />
      <section className="container my-5">
        <div className="row">
          <div className="col-12 col-lg-8">
            <Animated
              animationIn="fadeIn"
              animationOut="fadeOut"
              animationInDuration={1000}
              isVisible={true}
            >
              <img className="img-fluid vw-100" src={image} alt={name} />
            </Animated>
          </div>
          <div className="col-12 col-lg-4">
            <Animated
              animationIn="fadeIn"
              animationOut="fadeOut"
              animationInDuration={1000}
              isVisible={true}
            >
              <div className="mt-3 mt-lg-0">
                <h2>Project Info:</h2>
                <p>{content}</p>
                <hr></hr>
                <div className="d-flex justify-content-between mb-5">
                  <span className="d-flex align-items-center">
                    <FaLink />
                    <span className="text-bold ps-2">URL:</span>
                  </span>
                  <a href={projectURL} rel="noreferrer" target="_blank">
                    {projectURL}
                  </a>
                </div>
                <LinkContainer to="/projects">
                  <div className="text-left">
                    <Button
                      variant="primary"
                      className="d-flex align-items-center"
                      size="lg"
                    >
                      <FaAngleLeft className="me-2" />
                      Back to Projects
                    </Button>
                  </div>
                </LinkContainer>
                {/* I would like this button to navigate to the next project's id pulled from my data.js array.  */}
                <Button variant="primary" size="lg">
                  Next
                </Button>
              </div>
            </Animated>
          </div>
        </div>
      </section>
    </>
  );
}

export default SingleProject;

CodePudding user response:

  1. Find the index of current project. You can use for loop, findIndex, etc.
  2. projects[currentIndex 1] will be your next project. Check that currentIndex 1 is not greater than the projects last index.
// Inside your render function. For instance below the line you declare `project`.
const currentProjectIndex = projects.findIndex(project => project.id === projectId)
const nextProject = projects[currentProjectIndex   1]

You have 2 options to navigate:

useNavigate There is a useNavigate hook which you can import from react-router. It returns a function which lets you to navigate to a different URL.

  const navigate = useNavigate();

Call

navigate(`/projects/${nextProject.id}`)

inside onClick event handler of the button you want. Make sure that nextProject exists before you call the navigate function.

Link

You can import the Link component from react-router-dom' and render it instead of button component.

<Link to={`/projects/${nextProject.id}`}> Next</Link>
  • Related