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

问题描述 投票:4回答:2

我有这样的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" alt="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);
javascript node.js api react-redux redux-thunk
2个回答
1
投票

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

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

dispatch({ type: SEARCH_TERM, payload: query });

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

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


0
投票

根据redux-thunk-docs,在“动机”部分,

只有在满足某个条件时,才可以使用thunk进行调度。内部函数接收存储方法dispatch和getState作为参数。

现在,我觉得这很简单......

另外,我绝对不会在传递控制流之前触发AJAX-Method,而是通过返回处理...活动的Async-Promise的函数。我只是在返回的函数中推送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

© www.soinside.com 2019 - 2024. All rights reserved.