The ideal solution for this, in my opinion, is to use Reselect selectors ( https://github.com/reactjs/reselect ). Here is a contrived example:
import { createSelector } from 'reselect'; const getObjs = state => state.objs; const currentObjId = state => state.currentObjId; export const getObj = createSelector( [ currentObjId, getObjs ], (id, objs) => objs.get(href) );
Used as follows:
import { getObj } from './selectors'; const ExampleComponent = ({obj}) => <div>{ obj.name }</div>; const mapStateToProps = state => ({ obj: getObj(state) }); export default connect(mapStateToProps)(ExampleComponent);
The first time you run this, one of obj based on some id (also in state) will be "selected" from the list of all objs . Next time, if the inputs have not changed (look at re-fetching the documentation to determine equivalence), it will simply return the calculated value from the last time.
You also have the option of connecting a different type of cache, for example. LRU. It is a bit more advanced but very doable.
The main advantage of Reselect is that it allows you to purely optimize without manually saving the additional state in the redux, which you would need to remember if you changed the original data. Timo's answer is good, but I would say that the weakness is that it does not cache expensive client-side computing (I know this is not an exact question, but this answer concerns the best use of caching in the general case, applicable to your problem), only sampling. You can do something very similar to what Timo offers, but enable re-selection for a very neat solution. In the action creator, you can have something like this:
export const fetchObj = (dispatch, getState) => { if (hasObj(getState())) { return Promise.resolve(); } return fetchSomething() .then(data => { dispatch(receiveObj(data)); return data; }); };
You would have a selector specifically for hasObj , potentially based on the above selector (here, I specifically show here how easy it is to group selectors), for example:
export const hasObj = createSelector( [ getObj ], obj => !!obj );
As soon as you start using this for interacting with redux, it makes sense to use it exclusively in mapStateToProps even for simple samples, so that in the future, if the method of calculating this state has changed, you do not need to change all the components that use this state. An example of this might be something like a TODO array when used to render a list in several different components. Later in the application development process, you realize that you want to filter this TODO list by default only for incomplete ones. You change the selector in one place, and you're done.