Home > database >  react-router v6 double rendering components
react-router v6 double rendering components

Time:04-19

This is my first CRA/ typescript, SPA project so apologies if this is a beginner question. Initially, all my routing is going to be handled via my navbar.

Thus far when you click the navbar you do get the component at the top of the screen as desired but if you scroll down you also get the repeated initial page layout.

So my question is how do I anchor my nav links to a component rather than just bringing that component to the top of the page to be repeated again. Below is a link to my code.

index.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { render } from "react-dom";
import './index.scss';
import App from './components/App/App';
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Gallery from './components/Gallery/Gallery';
import About from './components/About/About';


const rootElement = document.getElementById("root");
render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<App />}>
        <Route path="/about" element={<About />} />
        <Route path="/gallery" element={<Gallery />} />
      </Route>
    </Routes>
  </BrowserRouter>,
  rootElement
);

App.jsx

import './App.scss';
import React from 'react';
import NavBar from '../NavBar/NavBar.tsx';
import About from '../About/About.tsx';
import GalleryCard from '../Gallery/Gallery.tsx';
import Divider from '@mui/material/Divider';


const App = () => {
  const background =  require("../../assets/images/45-degree-fabric-light.png")

  return (
    <div className="App">
      <div className='background'>
        <img src={background} className='background' alt="background" />
      </div>
      <NavBar/>
      <Divider className='divider' textAlign="left">GALLERY</Divider>
      <div className='card-container'>
        <GalleryCard/>
      </div>
      <Divider className='divider' textAlign="left">ABOUT</Divider>
      <About/>

    </div>
  );
}

export default App;

NavBar.tsx

import React from 'react';
import { Link, Outlet} from "react-router-dom";
import HomeButton from './HomeButton';
import './navbar.scss';


const NavBar = () => {

    return (
        <>
        <nav className='nav-container'>
      <Link to='/'><HomeButton/></Link>
            <div className='inner-container'>
                <div className='nav-links'>
                    <Link to='/' className='nav-link' >Home</Link>
                    <Link to='/gallery' className='nav-link' >Gallery</Link>
                    <Link to='/about' className='nav-link' >About</Link>
                    <Link to='/videos' className='nav-link' >Videos</Link>
                    <Link to='/contact' className='nav-link' >Contact</Link>
                </div>
            </div>
        </nav>
        <Outlet />
        </>
    )

}
export default NavBar;

CodePudding user response:

The GalleryCard and About components are rendered twice because they are rendered in two places.

index

<Routes>
  <Route path="/" element={<App />}>
    <Route path="/about" element={<About />} />     // <-- here
    <Route path="/gallery" element={<Gallery />} /> // <-- here
  </Route>
</Routes>

App

const App = () => {
  const background =  require("../../assets/images/45-degree-fabric-light.png")

  return (
    <div className="App">
      <div className='background'>
        <img src={background} className='background' alt="background" />
      </div>
      <NavBar/>
      <Divider className='divider' textAlign="left">GALLERY</Divider>
      <div className='card-container'>
        <GalleryCard/> // <-- and here
      </div>
      <Divider className='divider' textAlign="left">ABOUT</Divider>
      <About/> // <-- and here
    </div>
  );
}

Remove them from App, replace them with an Outlet component so the nested routes render out there in their place.

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

...

const App = () => {
  const background =  require("../../assets/images/45-degree-fabric-light.png")

  return (
    <div className="App">
      <div className='background'>
        <img src={background} className='background' alt="background" />
      </div>
      <NavBar/>
      <Outlet />
    </div>
  );
}

Move the divider and title to the components.

  • Related