我需要什么:
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中这样做的方法。
答案 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)
关联delay
和takeLatest
:
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];