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.
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.
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.