Redux thunk - how to prevent it from unnecessary API request?

I have an action.js file as follows:

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

Using reducers, I save up to reduction, keeping all the search terms that the user enters. Then I run the request on github api and save the response data.

Now I have a problem, and I really don't know how to deal with it yet.

How can I write code that checks that the user has already searched for this request before, in which case my application will not run this request in the github api.

How can I do this and where should I put this logic? Any ideas?


EDIT: Thanks @klugjo! Due to his hint, I wrote code that really worked.

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);
+4
source share
2

React.

, :

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

.jsx , .

-, redux -. .

+1

redux-thunk-docs, β†’ < ,

Thunk [...] . , 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
      })();
  };
}

, , , , . Cheers, J

0

Source: https://habr.com/ru/post/1691336/


All Articles