How do I keep App() level state from resetting with react-router-dom in React.js?

I have a hook that changes the background color of my app. I would like the background color to stay changed when navigating through the site, but the Router resets this state back to its original useState of ‘white’. How do I implement this correctly?

Created with create-react-app.

Edited to show minimum reproducible example:

import React, { useState } from 'react';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
import './App.css';

export default function App() {
  const [color, setColor] = useState('white');

  function changeBackground(value) {
    setColor(value);
  };

  return (
    <div className={color}>
      <BrowserRouter>
        <Navbar changeBackground={changeBackground} />
      </BrowserRouter>
    </div>
  );
};

function Navbar(props) {

  return (
    <div>
      <button onClick={() => props.changeBackground('red')}>
        Change Background Color
      </button>
      <div>
        <a href="/page1">Page 1</a>
      </div>
      <div>
        <a href="/page2">Page2</a>
      </div>
      <Switch>
        <Route exact path="/page1"><Page1 /></Route>
        <Route exact path="/page2"><Page2 /></Route>
      </Switch>
    </div>
  );
};

function Page1() {

  return (
    <div>
      Page 1
    </div>
  );
};

function Page2() {

  return (
    <div>
      Page 2
    </div>
  );
};
/* App.css */
.white {
  background-color: white;
}
.red {
  background-color: red;
}

Previous code before adding minimum reproducible example:

import React, { useState } from 'react';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
import './App.css';
import './assets/fonts/fonts.css';
import Navbar from './components/Navbar';
import Design from './components/Design';
import Develop from './components/Develop';
import Else from './components/Else';
import DesignTest from './pages/DesignTest';

function App() {
  const [backgroundColor, setBackgroundColor] = useState('white');


  function changeBackground(value) {
    setBackgroundColor(value);
  };


  return (
    <div className={`w-screen min-h-screen ${backgroundColor}`}>
      {/* <Router> */}
      <Navbar changeBackground={changeBackground} />
      <BrowserRouter>
        <Switch>
          <Route exact path="/"></Route>
          <Route exact path="/design"><Design /></Route>
          <Route exact path="/develop"><Develop /></Route>
          <Route exact path="/else"><Else /></Route>
          <Route exact path="/design/test"><DesignTest /></Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

function Navbar(props) {

  return (
  <div className="w-screen h-screen inline-grid grid-cols-12 grid-rows-6 tuffyBold tracking-widest">
            <div className="row-start-1 row-end-3 col-start-1 col-end-7 text-right mt-auto mb-auto text-5xl">
              TITLE
         </div>
              <div className="row-start-3 row-end-4 col-start-7 col-end-13 test-left mt-auto mb-auto text-4xl">
                <a href="/design">
                  DESIGN
                </a>
              </div>
              <div className="row-start-4 row-end-5 col-start-7 col-end-13 test-left mt-auto mb-auto text-4xl">
                <a href="/develop">
                  DEVELOP
                </a>
              </div>
              <div className="row-start-5 row-end-7 col-start-7 col-end-13 test-left mt-auto mb-auto text-4xl">
                <a href="/else">
                  EVERY<br />THING<br />ELSE
                </a>
              </div>
            <div className="row-start-1 row-end-3 col-start-7 col-end-13 mt-auto mb-auto ml-auto mr-auto">
              <div className="circle white" onClick={() => props.changeBackground('white')}></div>
            </div>
            <div className="row-start-3 row-end-4 col-start-1 col-end-7 mt-auto mb-auto ml-auto mr-auto">
              <div className="circle yellow" onClick={() => props.changeBackground('yellow')}></div>
            </div>
            <div className="row-start-4 row-end-5 col-start-1 col-end-7 mt-auto mb-auto ml-auto mr-auto">
              <div className="circle blue" onClick={() => props.changeBackground('blue')}></div>
            </div>
            <div className="row-start-5 row-end-6 col-start-1 col-end-7 mt-auto mb-auto ml-auto mr-auto">
              <div className="circle dark" onClick={() => props.changeBackground('dark')}></div>
            </div>
          </div>
          
            );
}

export default Navbar;
.yellow {
  background-color: #CDB900;
  color: black;
}
.blue {
  background-color: #009CCD;
  color: black;
}
.dark {
  background-color: #4B394E;
  color: white;
}
.white {
  background-color: white;
  color: black;
}

Answer

I found my issue. I was using <a href="/#"> instead of importing Link from react-router-dom, causing the entire page to re-render. Here is the version that worked as I intended:

import React, { useState } from 'react';
import { Route, Switch, BrowserRouter, Link } from 'react-router-dom';
import './App.css';

export default function App() {
  const [color, setColor] = useState('white');

  function changeBackground(value) {
    setColor(value);
  };

  return (
    <div className={color}>
      <BrowserRouter>
        <Navbar changeBackground={changeBackground} />
      </BrowserRouter>
    </div>
  );
};

function Navbar(props) {

  return (
    <div>
      <button onClick={() => props.changeBackground('red')}>
        Change Background Color
      </button>
      <div>
        <Link to="/page1">Page 1</Link>
      </div>
      <div>
        <Link to="/page2">Page2</Link>
      </div>
      <Switch>
        <Route exact path="/page1"><Page1 /></Route>
        <Route exact path="/page2"><Page2 /></Route>
      </Switch>
    </div>
  );
};

function Page1() {

  return (
    <div>
      Page 1
    </div>
  );
};

function Page2() {

  return (
    <div>
      Page 2
    </div>
  );
};
/* App.css */
.white {
  background-color: white;
}
.red {
  background-color: red;
}

Leave a Reply

Your email address will not be published. Required fields are marked *