In my React based application, there is a rest API call which fetches all the data in one shot which is needed for the whole page. The response has data which can be used in a p
As I guessed you are using redux for state management. And You want to cache api calls for efficient controll state changes for avoiding rerendering Components, unnecessarry API calls and being friendly for Mobile Users (with avoiding fetchig same data(not changed) multiple time). If so -> then you can use ready solution for it.
redux-cache. please visit below link for additional information and investigate caching mechanizm briefly -> when you need cache data and when you need evict cache.
https://github.com/JumboInteractiveLimited/redux-cache
How do I implement caching in Redux?
you can cache in HDD or RAM.
For localStorage you can use my little plugin for this: https://www.npmjs.com/package/localstorage-ttl
In app state (RAM) - fire action to fetch data, use redux-thunk, redux-saga or similar to make a call and with reducer save data in the store. Retrieve data from store.
https://github.com/gaearon/redux-thunk https://github.com/redux-saga/redux-saga
You could choose a redux-cached-api-middleware (disclaimer: I'm the author of this library), that's especially built for such cases.
Here's an example that might fit your case:
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import api from 'redux-cached-api-middleware';
import Dropdown from './Dropdown';
import Error from './Error';
class ExampleApp extends React.Component {
componentDidMount() {
this.props.fetchData();
}
render() {
const { result } = this.props;
if (!result) return null;
if (result.fetching) return <div>Loading...</div>;
if (result.error) return <Error data={result.errorPayload} />;
if (result.successPayload) return <Dropdown items={result.successPayload} />;
return <div>No items</div>;
}
}
ExampleApp.propTypes = {
fetchData: PropTypes.func.isRequired,
result: PropTypes.shape({}),
};
const CACHE_KEY = 'GET/items';
const enhance = connect(
state => ({
result: api.selectors.getResult(state, CACHE_KEY),
}),
dispatch => ({
fetchData() {
return dispatch(
api.actions.invoke({
method: 'GET',
headers: { Accept: 'application/json' },
endpoint: 'https://my-api.com/items/',
cache: {
key: CACHE_KEY,
strategy: api.cache
.get(api.constants.SIMPLE_SUCCESS)
.buildStrategy(),
},
})
);
},
})
);
export default enhance(ExampleApp);
It will fetch from API only once, and whenever you call fetchData
it will return data from the cache, even if the call is from another component.
The setup for this library is as follows:
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { apiMiddleware } from 'redux-api-middleware';
import api from 'redux-cached-api-middleware';
import reducers from './reducers';
const store = createStore(
combineReducers({
...reducers,
[api.constants.NAME]: api.reducer,
}),
applyMiddleware(thunk, apiMiddleware)
);
With this approach after user re-loads the page all redux state will be lost, if you'd like to save that state you could choose a redux-persist library to sync the state to localStorage
and use would probably use different caching strategy for redux-cached-api-middleware
.