skip to Main Content

So I have 2 pages 1. customer-list, 2. customer-detail. so customer-list page will be a table where it contains a list of a customer-id without the details but there’s a button which will navigate to another page customer detail. the code looks like this

const CustomerList = () => {
   const [customers, setCustomers] = useState([]);
   useEffect(() => { fetch customer list here }, [])

   return (
      { 
         customers.map(c => 
            <tr>
              <td>{customer.customer_id}</td>
              <td><button onClick={() => navigate(`/customer/${customer.customer_id}`)}>View details</button></td>
           </tr>
         ) 
      }
   );
}

In the customer details page there’s also a button where it can navigate back to the previous page, customer-list, the code looks like this.

const CustomerDetails = () => {
   const navigate = useNavigate();

   return (
       <>
        <h2>Customer Details</h2>
        <button onClick={() => navigate(-1)}>Back</button>
       </>
   );
}

however when I navigate back to the first page it will completely re-render and fetch the whole data again. Is there a way to cache or prevent the first page from re-rendering or re-load the data because it took very long time to load the customer list so I’m concerning about the user experience here. I’m using react-router-dom v6 and the path structure looks like this.

/ -> root customer-list
/customer/:customerId -> customer-details

2

Answers


  1. With the way you have implemented your CustomerList component, it will always try to fetch the API whenever it mounts, because the state is local to that component only. To prevent this from happening, you have few options

    1. Move the customers state to its Parent and pass it via props to CustomerList component. Please keep in mind that if that Parent is also something that gets unmonted & remounted on route changes, then this will still happen. So you will have to lift the state again till a Parent that is always rendered. You can decide this based on whether or not its good to keep this data in such a parent

    2. Use a global state solution. This way, data will be kept separate from your components so that it is not lost when you navigate back and forth. Redux is one of them. There are many also.

    3. Use some data fetching libraries like SWR or TanstackQuery. They have builtin mechanisms to keep the cache

    Login or Signup to reply.
  2. You can use https://reactrouter.com/en/main/components/outlet , to achieve this behavior. There is an amazing example on the link I provided

    From the link

    function Dashboard() {
      return (
        <div>
          <h1>Dashboard</h1>
    
          {/* This element will render either <DashboardMessages> when the URL is
              "/messages", <DashboardTasks> at "/tasks", or null if it is "/"
          */}
          <Outlet />
        </div>
      );
    }
    
    function App() {
      return (
        <Routes>
          <Route path="/" element={<Dashboard />}>
            <Route
              path="messages"
              element={<DashboardMessages />}
            />
            <Route path="tasks" element={<DashboardTasks />} />
          </Route>
        </Routes>
      );
    }
    

    Or if don’t wanna change your current routing setup and not use a global state manager you can use localStorage, sessionStorage or any browser storage API that would fit your use case, this will persist your data and you don’t need to re-fetch it.

    https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search