确定Redux中的单个项目的本地缓存是否过时

时间:2016-09-19 10:08:11

标签: javascript reactjs redux

Redux Async示例中,有一个名为shouldFetch的函数,它接收(state, subreddit)并返回是否应该获取给定subreddit中的项目。

你怎么能可靠地做同样的事情,但对于单个项目?这意味着一个函数需要shouldFetch(state, subreddit, id)并返回Boolean

真正的问题是如何保留每个项目获取时的metadata?我们将在lastUpdated中提取列表时存储,但不会在每个项目上次更新时存储。

你需要: 1.确定项目是否在缓存中(存储) 2.确定当前是否正在获取此当前项目(通过列表获取或通过单独获取) 3.确定该项目是否陈旧。

除了为lastUpdated / isFetching构建客户端数据库之外,还有什么好的方法可以实现吗?

2 个答案:

答案 0 :(得分:0)

  

你怎么能可靠地做同样的事情,但对于单个项目?这意味着一个函数接受shouldFetch(state,subreddit,id)并返回Boolean。

作为链接中的shouldFetchPosts函数,您必须创建自己的函数,以检查某些元数据是否有某些内容。这部分不是关于redux,而是关于你的元数据,你如何在redux商店中塑造你的数据,或者你需要的元数据是否在你的服务器响应中是可用的。

因此,您必须创建一个函数,该函数接收一些数据并检查您在函数体中编写的逻辑的给定数据。

  

真正的问题是如何保留每个项目获取时的元数据?我们在lastUpdated中提取列表时存储,但在上次更新每个项目时不存储。

您是说您是在更新列表项而不是要求更新列表的服务器请求?如果没有,如果你只是发送更新项目的请求,也可能更新你的redux状态的项目,这听起来还不错。由于您的应用程序是SPA,如果您确定服务器上的数据已更改,则可以轻松更改redux状态,并且可能不会发出服务器请求。

  

您将需要:1。确定项目是否在缓存(存储)中是否均匀2.确定当前是否正在获取此当前项目(通过列表获取或通过单独获取)3。确定项目是否陈旧与否。

现在我的想法是,您实际上应该检查某些数据是否已过时,如果正在提取某些内容,您不应该允许您的用户触发重新获取,如果某些数据不是陈旧的话,您可以轻松地在组件中创建一个函数,该函数决定是否需要用户触发的操作。

将所有这些逻辑移至redux操作会使您的redux文件变得难看。但是,你可以塑造你的redux状态,随时改进它并检查状态中的一些元数据以制作干扰。

答案 1 :(得分:0)

我实际上构建了一个redux-cached-api-middleware软件包,该软件包有助于以缓存的方式与API进行交互。它保留了获取完成时间戳,可以帮助确定缓存是否陈旧。例如:

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import api from 'redux-cached-api-middleware';
import Items from './Items';
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 <Items data={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.CACHE_TYPES.TTL_SUCCESS)
              .buildStrategy({ ttl: 10 * 60 * 1000 }), // 10 minutes
          },
        })
      );
    },
  })
);

export default enhance(ExampleApp);

此组件使用一种缓存策略来确定在调用this.props.fetchData();函数时是否应重新获取资源。

如果您有更复杂的方法来确定缓存的有效性,则还可以提供自定义shouldFetch函数:

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   
            shouldFetch({ state }) { // CachedApiState object
              // Define your logic when the resource should be re-fetched
              return true;
            }
          },
        })
      );
    },
  })
);

* CachedApiState对象由以下字段组成:

{
  fetching: boolean, // is fetching in progress
  fetched: boolean, // was any fetch completed
  error: boolean, // was last response an error
  timestamp: ?number, // last response timestamp
  successPayload: ?any, // last success response payload
  errorPayload: ?any, // last error response payload
}