Sidebar Routing with state management and re-fetching

Viewed 171

I am having a hard time understanding how to route using a sidebar and conditionally reloading the state. what I mean is that I would like when a route in the sidebar is chosen, data for that route is loaded into the main container to the right of the sidebar.

​

When clicking on a couple routes, I would like the user to be able to go back to the previous route, without having to re-fetch the data. I know how to lift the state and that works for not re-fetching on page back. The issue is when the link is clicked again, purposefully, I WOULD like the data to be re-fetched but the old state is shown instead.

​

Approach 1 lifted state:

  1. Main container component is loaded, data for each route is manually fetched (inefficient but was testing)
  2. State is then passed to route in said component
  3. Can go back and forward without reloading.
  4. Clicking on "Hone" after being on "Item", nothing is re-fetched, old data always displayed.

​

Approach 2 state in component:

  1. Routes are loaded on routing on when sidebar items are clicked.
  2. Fetch handled locally in component
  3. Going back or forward re-fetches
  4. Clicking on "Hone" after being on "Item", will re-fetch the data as intended.

​

I have tried so many different ways, but I can only ever hold the state indefinitely or fetch on back each time. No hybrid fetching and state caching as I would like. Been at this for the last two days and I give up. The code is below with the component based local state/constant route re-fetching. Any help would be greatly appreciated.

Main Container

import React from "react";
import SideBar from "./Sidebar";
import Header from "./Header";
import Routes from "./Routes";

function MainContainer() {
    return (
        <>
            <div className="main-sidebar">
                <SideBar />
            </div>
            <div className="main-content">
                <Header />
                <Routes />
            </div>
        </>
    );
}

export default MainContainer;

Sidebar

import React from "react";
import { NavLink } from "react-router-dom";
import Nav from "react-bootstrap/Nav";

function SideBar({ onClick }) {
    const linkItems = [
        { name: "Home", to: "/" },
        { name: "Item", to: "/item" },
        { name: "Dashboard", to: "/dashboard" },
    ];

    const sidebarItems = linkItems.map((item) => (
        <Nav.Item key={item.to}>
            <NavLink exact to={item.to} activeClassName="sidebar-active-nav" className="nav-link sidebar-inactive-nav">
                <h3>{item.name}</h3>
            </NavLink>
        </Nav.Item>
    ));

    return <Nav className="flex-column">{sidebarItems}</Nav>;
}

export default SideBar;

Routes

import React from "react";
import { Switch, Route } from "react-router-dom";
import Dashboard from "./Dashboard";
import Item from "./Item";
import Home from "./Home";

function Routes() {
    return (
        <div className="container-fluid">
            <Switch>
                <Route path="/" exact render={(props) => <Home key="1" {...props} />} />
                <Route path="/item" render={(props) => <Item key="2" {...props} />} />
                <Route path="/dashboard" render={(props) => <Dashboard key="3" {...props} />} />
            </Switch>
        </div>
    );
}

export default Routes;

Example of a route component

import { useEffect } from "react";
import Component from "react-bootstrap/Container";
import Spinner from "react-bootstrap/Spinner";
import useFetch from "../helpers/Fetcher";

function Dashboard() {
    const [data, loading] = useFetch("https://raw.githubusercontent.com/epicmau5time/demo/master/test.json");

    useEffect(() => {
        return () => {
            console.log("cleaned up");
        };
    }, []);

    return (
        <Component className="page-container">
            <h2>Dashboard</h2>
            {!loading && data ? (
                data.map((data) => (
                    <div key={data.id}>
                        <p>{data.title}</p>
                    </div>
                ))
            ) : (
                <div className="justify-content-center text-center">
                    <Spinner className="" animation="border" variant="primary" role="status">
                        <span className="sr-only">Loading...</span>
                    </Spinner>
                </div>
            )}
        </Component>
    );
}

export default Dashboard;

Fetching helper

0 Answers
Related