如何在React和Redux中缓存API响应并稍后使用?

18
在我的 React 应用程序中,有一个 REST API 调用一次性获取整个页面所需的所有数据。响应数据可以用于下拉菜单的填充,但我不确定如何实现。目前,每当选择下拉列表的值时,都会发起新的请求。请建议如何高效地实现,避免多次不必要的 REST 调用。

你好,你实现了这个吗?如果是,请告诉我怎么做? - Johnson
是的..我已经实现了这个.. 你需要创建一个状态变量来保存JSON响应或数据。 然后使用willreceiveprops和render,您可以使用状态变量并实现它。 - A srinivas
5个回答

27
你可以将数据缓存到硬盘或内存中。
  • 硬盘缓存 = 例如localStorage
  • 内存缓存 = 应用程序状态,例如redux store。

对于localStorage,你可以使用我的小插件: https://www.npmjs.com/package/localstorage-ttl

在应用程序状态中(内存中) - 触发操作以获取数据,并使用redux-thunk、redux-saga或类似工具进行调用并使用reducer将数据保存在store中。从store中检索数据。

https://github.com/gaearon/redux-thunk https://github.com/redux-saga/redux-saga


1
我加了+1。我觉得有人(放了-1)不明白redux和浏览器存储在内部的位置;))) - Musa

9
你可以选择使用 redux-cached-api-middleware(免责声明:我是这个库的作者),它专门用于处理类似的情况。
以下是一个适合你情况的示例:
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);

这个库只会从API获取一次数据,每次你调用 fetchData 时,它都会从缓存中返回数据,即使调用来自另一个组件。

这个库的设置如下:

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)
);

采用这种方法后,用户重新加载页面后所有的Redux状态都将丢失。如果您想保存该状态,可以选择redux-persist库将状态同步到localStorage,并可能会使用不同的缓存策略来处理redux-cached-api-middleware


你有这方面的任何示例样本吗? - Akbar Basha
@AkbarBasha 是的,我已经制作了一些[demos][https://github.com/buz-zard/redux-cached-api-middleware#demos]。 - Karolis.sh
谢谢,我也在那个部分中调用了API,我该如何使用你的代码? - Akbar Basha
我在这里调用了API,您能否给出建议,帮助我实现这个需求?您能提供任何指南吗?最好附带示例,对我来说非常有帮助。谢谢@Karolis。 - Akbar Basha
不必要的 https://web.dev/http-cache/ - 你可以通过调整API的响应来使浏览器缓存它们,而无需在客户端进行缓存...当然,如果你能控制网络API的话。 - Tkoma
显示剩余2条评论

1
你可以使用这个NPM库,它内置了缓存。看起来正是你所需要的。

https://www.npmjs.com/package/reqmate

检查一下示例
  const response = await reqmate
  .get('https://jsonplaceholder.typicode.com/todos/1')
  .setCaching(3000) 
  .send();

设置缓存后,它会自动检测是否发送相同的缓存请求,并在缓存过期之前提供缓存中的内容。

0

正如我的猜测,您正在使用redux进行状态管理。您想要缓存API调用以有效地控制状态更改,避免重新渲染组件、不必要的API调用并对移动用户友好(避免多次获取相同数据(未更改))。如果是这样->那么您可以使用现成的解决方案。

redux-cache.请访问下面的链接以获取更多信息,并简要探讨缓存机制->何时需要缓存数据以及何时需要删除缓存。

https://github.com/JumboInteractiveLimited/redux-cache

如何在Redux中实现缓存?


0

不适用于授权的端点。 - Noone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接