正确的方法来基于redux中的状态来限制HTTP调用并做出反应

时间:2016-04-13 15:06:11

标签: reactjs redux

我需要什么: controlled component input[type="search"]dispatch(setSearch(str));。比如说,1秒没有对该组件进行任何更改,我想发出一个HTTP调用来执行该搜索并将结果显示在另一个组件中。

我是怎么做到的: 每当我拨打dispatch(displaySearch(false));时,我都会拨打_.throttle,然后dispatch(displaySearch(true));拨打START TRANSACTION; INSERT INTO `file` (`name`, `mime_type`, `size`, `comment`) VALUES ('file.png', 'image/png', '1024', 'My comment'); INSERT INTO `complementary_file` (`file_id`, `user_id`) VALUES (LAST_INSERT_ID(), '1'); COMMIT;

我觉得在组件中进行这种工作是不正确的,但我想不出在redux中的reducer中这样做的方法。

2 个答案:

答案 0 :(得分:9)

你有不同的选择来解决这个问题。

<强> 1。在组件级别撤销您的操作

这是最简单的方法。当输入触发更改时,它会调用 去抖动版本setSearch延迟服务器调用。

import * as React from "react"
import {connect} from "react-redux"
import {setSearch} from "./actions"

export default connect(
  null,
  function mapDispatchToProps(dispatch) {
    const setSearch_ = _.debounce(q => dispatch(setSearch(q)), 1000)
    return () => ({setSearch: setSearch_})
  }
)(
  function SearchForm(props) {
    const {setSearch} = props
    return (
      <input type="search" onChange={setSearch} />
    )
  }
)

<强> 2。使用redux-saga

进行去抖动

这种方法需要更多样板,但可以让你更多地控制 工作流程。使用 saga 我们拦截SET_SEARCH动作,去抖动, 调用API然后调度包含结果的新操作。

import {call, cancel, fork, put, take} from "redux-saga/effects"
import {setSearchResults} from "./actions"
import {api} from "./services"
import {delay} from "./utils"

export default function* searchSaga() {
  yield [
    // Start a watcher to handle search workflow
    fork(watchSearch)
  ]
}

function* watchSearch() {
  let task

  // Start a worker listening for `SET_SEARCH` actions.
  while (true) {
    // Read the query from the action
    const {q} = yield take("SET_SEARCH")

    // If there is any pending search task then cancel it
    if (task) {
      yield cancel(task)
    }

    // Create a worker to proceed search
    task = yield fork(handleSearch, q)
  }
}

function* handleSearch(q) {
  // Debounce by 1s. This will lock the process for one second before
  // performing its logic. Since the process is blocked, it can be cancelled
  // by `watchSearch` if there are any other actions.
  yield call(delay, 1000)

  // This is basically `api.doSearch(q)`. The call should return a `Promise`
  // that will resolve the server response.
  const results = yield call(api.doSearch, q)

  // Dispatch an action to notify the UI
  yield put(setSearchResults(results))
}

答案 1 :(得分:1)

关联delaytakeLatest

import { all, takeLatest, call } from 'redux-saga/effects';
import { delay } from 'redux-saga';


function* onSearch(action) {
  yield call(delay, 1000); // blocks until a new action is
                           // triggered (takeLatest) or until
                           // the delay of 1s is over  

  const results = yield call(myFunction);
}

function* searchSagas() {
  yield all([
    // ...
    takeLatest(ON_SEARCH, onSearch),
  ]);
}

export default [searchSagas];