How to cache fetched data in react without redux

I know, using Redux I have common store and when I change my location, for example I went from /videos page, but I still have fetched videos in my videos reducer. So if I then decide to go back to my videos page I show user already loaded videos from my store, and will load more if he needs and store them.

But in React without Redux if I change my location /videos where I fetched some videos and then stored them in my local state of my VideosPage component and then went back to this page, I have no videos anymore and should fetch them from scratch.

How can I cache them and is it possible at all?

PS: This is more theoretical question so no code provided.

The best way to save data when you want to repopulate it at a later point of time is to save it in localStorage, which allows you to get the data even after refreshing the app

const InitialState = {
   someState: 'a'
}
class App extends Component {

 constructor(props) {
  super(props);

  // Retrieve the last state
  this.state = localStorage.getItem("appState") ? JSON.parse(localStorage.getItem("appState")) : InitialState;

}

componentWillUnmount() {
  // Remember state for the next mount
  localStorage.setItem('appState', JSON.stringify(this.state));
}

render() {
  ...
 }
}

export default App;

While the presently accepted answer (storing the state in localStorage) can get the job done, I hesitate to advise doing it as it breaks a lot of patterns. You will now be driving state management partially outside of the React ecosystem, violating the state machine pattern and making your app dependent on an external global variable. So long as it is only a cache and only being accessed and set in this one location, it won’t be the worst sin, but you never know when you’ll have a developer come by and think “oh hey, I have this state being stored in localStorage, I’ll just grab it that way,” and then you’re in for some trouble.

Read More:   Vue-router error: TypeError: Cannot read property 'matched' of undefined

Instead, I’d suggest one of the following:

  • Storing the state in a parent component that isn’t unmounting and giving access to the data and the state setter to your relevant component through props.

  • Setting up a context provider for the state, storing it there, and then subscribing to that context where you need it with the useState hook or a context consumer.

Each approach as some cons, for example, with the first option you’ll need to do more prop drilling and you’ll be storing state at a level of abstraction that isn’t directly concerned with it, while in the latter case using a context might be a bit heavy-weight if you’re only using the state in one place or one component-layer deep, but I’ll leave it up to you to judge which approach is simpler for your use case.

Either one will keep all of your state management within the React ecosystem and avoid any pattern violations by yourself or future developers who don’t understand the present rationale.

You can cache with:-

1) Local Storage

2) Redux Store

3) Keep data between mouting and unmounting

import React, { Component, PropTypes } from 'react';

// Set initial state
let state = { counter: 5 };

class Counter extends Component {

 constructor(props) {
  super(props);

  // Retrieve the last state
  this.state = state;

  this.onClick = this.onClick.bind(this);
}

componentWillUnmount() {
  // Remember state for the next mount
  state = this.state;
}

onClick(e) {
  e.preventDefault();
  this.setState(prev => ({ counter: prev.counter + 1 }));
}

render() {
  return (
    <div>
      <span>{ this.state.counter }</span>
      <button onClick={this.onClick}>Increase</button>
    </div>
  );
 }
}

export default Counter;

Your issue is that the component is unmounting when you navigate.

Read More:   How to return the response from an asynchronous call

You can lift the video state up to a component that won’t unmount.

or

If you are avoiding redux and depending on how you are handling navigation you can always have your video container mounted and if the route matches it renders videos otherwise it returns null.

If you want to save data (complex data type) in browser level (client-side), You can use IndexDb which is now compatible in most modern browsers.
IndexDB provides the transactional and index feature to save and fetch data at the browser level. And which is asynchronous.
Please follow this link to get more details of browser caching.

IndexedDB and Caching


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Similar Posts