Redux thunk - 如何防止它发出不必要的 API 请求?

Posted

技术标签:

【中文标题】Redux thunk - 如何防止它发出不必要的 API 请求?【英文标题】:Redux thunk - how to prevent it from making unnecessary API request? 【发布时间】:2018-06-06 23:21:45 【问题描述】:

我有这样的 action.js 文件:

import axios from 'axios';

export const SEARCH_TERM = 'SEARCH_TERM';
export const SAVE_SEARCH = 'SAVE_SEARCH';

export function search(query) 
  const githubApi = `https://api.github.com/search/repositories?q=$query&sort=stars&order=desc`;
  const request = axios.get(githubApi);
  return (dispatch) => 
    request.then(( data: dataFromGithub ) => 
      dispatch( type: SEARCH_TERM, payload: query );
      dispatch( type: SAVE_SEARCH, payloadOne: query, payloadTwo: dataFromGithub );
    );
  ;

我使用 reducer 保存到 redux 存储用户输入的所有搜索词。 然后我向 github api 发出请求并保存响应数据。

现在我有一个问题,我真的不知道如何处理它。

我如何编写代码来检查用户之前是否已经搜索过此查询,在这种情况下,我的应用不会向 github api 发出该请求。

我该怎么做?我应该把这个逻辑放在哪里?有什么想法吗?


编辑: 感谢@klugjo!由于他的暗示,我编写了确实有效的代码。

import React,  Component  from 'react';
import  connect  from 'react-redux';
import  bindActionCreators  from 'redux';
import _ from 'lodash';
import logo from './logo.svg';
import './style.css';

import SearchBar from '../SearchBar';

import  search  from '../../actions/';

class App extends Component 
  startSearch(query) 
    const storedTerms = this.props.storedSearchTerms;
    let foundDuplicate = false;

    if (storedTerms.length === 0) 
      return this.props.search(query);
    

    if (storedTerms.length !== 0) 
      const testDuplicate = storedTerms.map(term => term === query);
      foundDuplicate = testDuplicate.some(element => element);
    

    if (foundDuplicate) 
      return false;
    

    return this.props.search(query);
  

  render() 
    const searchDebounced = _.debounce(query => this.startSearch(query), 2000);
    return (
      <div className="App">
        <header className="App-header">
          <img src=logo className="App-logo"  />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started...
        </p>
        <SearchBar handleSearchQueryChange=searchDebounced />
      </div>
    );
  


function mapStateToProps(state) 
  return 
    storedSearchTerms: state.searchTerm,
  ;


function mapDispatchToProps(dispatch) 
  return bindActionCreators( search , dispatch);


export default connect(mapStateToProps, mapDispatchToProps)(App);

【问题讨论】:

【参考方案1】:

您必须从 React 组件内部进行检查。

根据您的代码,我会说您正在保存已执行的查询列表:

dispatch( type: SEARCH_TERM, payload: query );

在您的 .jsx 容器中,仅当该查询在您的过去查询列表中不存在时才执行搜索操作。

在我看来,从动作创建者中传递或访问你的 redux 状态是一种反模式。你可以阅读更多关于here的信息。

【讨论】:

【参考方案2】:

根据redux-thunk-docs,就在>>动机

只有在满足特定条件时才可以使用 thunk [...] 进行调度。内部函数接收 store 方法 dispatch 和 getState 作为参数。

现在,在我看来这很简单......

另外,在通过返回处理... active Async-Promise 的函数传递控制流之前,我绝对不会触发 AJAX 方法。我只是将 ajax 调用推送到返回函数中,这对于使其成为有条件的函数是必要的:)

export function search(query) 
  const githubApi = `https://api.github.com/search/repositories?q=$query&sort=stars&order=desc`;
  const request = axios.get.bind(axios, githubApi);
  return (dispatch, getStore) => 
    const  SaveSearchReducer  = getStore();
    // consider writing a proper regex or something that fits your need
    const redundantPayload = SaveSearchReducer.filter(payload => !!payload.payloadOne.match(query));

    redundantPayload.length === 0 ?
      request().then(( data: dataFromGithub ) => 
        dispatch( type: SEARCH_TERM, payload: query );
        dispatch( type: SAVE_SEARCH, payloadOne: query, payloadTwo: dataFromGithub );
      ) : 
      (() => 
        dispatch( type: SEARCH_TERM, payload: query );
        dispatch( type: SAVE_SEARCH, payloadOne: query, payloadTwo: redundantPayload[0].payloadTwo );
        // consider doing something more intelligent above here
        // you might have search terms that are contained by other search terms or similar and therefor might end up with multiple fitting previous searches/payloads
      )();
  ;

好的,我没有对此进行测试,因此可能存在错误或错误,但我认为它应该可以帮助您找到解决方案。干杯,J

【讨论】:

以上是关于Redux thunk - 如何防止它发出不必要的 API 请求?的主要内容,如果未能解决你的问题,请参考以下文章

Redux thunk:如何等待异步操作的完成

redux-thunk的理解

如何使用 Redux Thunk 处理 fetch() 响应中的错误?

使用 axios 和 redux-thunk 以 redux-form 发布请求

如何使用 redux-thunk `bindActionCreators`

使用 Redux Thunk 和 Axios 测试 Action Creator