如何在Redux中实现缓存? [英] How do I implement caching in Redux?

查看:76
本文介绍了如何在Redux中实现缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我的商店中已经有数据,我希望避免两次调用API.

I would like to avoid calling an API twice if I already have the data in my store.

如何使用Redux做到这一点?

How do I do this with Redux?

推荐答案

对此的理想解决方案是使用 Reselect 选择器(

The ideal solution to 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)
);

像这样使用:

import { getObj } from './selectors';

const ExampleComponent = ({obj}) => <div>{ obj.name }</div>;

const mapStateToProps = state => ({
  obj: getObj(state)
});

export default connect(mapStateToProps)(ExampleComponent);

第一次运行此命令时,将从所有 objs列表中选择"一个基于某些 id obj .下次,如果输入没有更改(请参阅重新选择文档以了解等效性),它将仅返回上次的计算值.

The first time you run this, one obj based on some id (also in the state) will be "selected" from the list of all objs. The next time, if the inputs have not changed (look at reselect documentation for the definition of equivalence) it will simply return the computed value from last time.

您还可以选择插入其他类型的缓存,例如LRU.有点高级,但是很可行.

You also have the option to plug-in a different type of cache, e.g. LRU. That's a bit more advanced, but very doable.

Reselect的主要优点在于,它可以使您进行干净的优化,而无需在redux中手动维护额外的状态,如果对原始数据进行了更改,则必须记住要对其进行更新.Timo的回答很好,但是我认为弱点在于它不会缓存昂贵的客户端计算(我知道这不是确切的问题,但这是关于最佳实践的一般Redux缓存,适用于您的问题),只能提取.您可以执行与Timo建议的操作非常相似的操作,但可以合并重新选择以获得非常整洁的解决方案.在动作创建者中,您可能会遇到类似这样的情况:

The major advantage of Reselect is that it allows you to cleanly optimise without manually maintaining extra state in redux that you would then have to remember to update if a change to the original data was made. Timo's answer is good, but I would argue that the weakness is that it doesn't cache expensive client side computation (I know this wasn't the exact question, but this answer is about best practice redux caching in general, applied to your problem), only fetching. You can do something very similar to what Timo suggests, but incorporate reselect for a very tidy solution. In an action creator you could have something like this:

export const fetchObj = (dispatch, getState) => {
  if (hasObj(getState())) {
    return Promise.resolve();
  }

  return fetchSomething()
    .then(data => {
      dispatch(receiveObj(data));
      return data;
    });
};

您可能有一个可能专门基于上述选择器的 hasObj 选择器(我在这里这样做是为了展示如何轻松组成选择器),例如:

You would have a selector specifically for hasObj potentially based on the above selector (I do so here specifically to show how you can compose selectors easily), like:

export const hasObj = createSelector(
  [ getObj ],
  obj => !!obj
);

一旦您开始使用它与redux进行接口,就开始在 mapStateToProps 中专门使用它,即使是简单选择也是如此,以便将来在更改状态的计算方式时使用,则无需修改使用该状态的所有组件的所有.这方面的一个例子可能是,当用于在几个不同组件中呈现列表时,具有一个TODO数组.在应用程序开发过程的后期,您会意识到您希望默认情况下将TODO列表筛选为不完整的列表.您只需将选择器更改到一个位置就可以了.

Once you start using this to interface with redux, it starts to make sense to use it exclusively in mapStateToProps even for simple selects so that at a future time, if the way that state is computed changes, you do not need to modify all of the components which use that state. An example of this might be something like having an array of TODOs when is used to render a list in several different components. Later in your application development process you realise you want to filter that list of TODOs by default to only ones that are incomplete. You change the selector in one place and you are done.

这篇关于如何在Redux中实现缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆