使用 redux 表单时如何将 Dispatch 传递给 action

How to pass Dispatch to action when using redux form

我有以下搜索组件

import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';

import { search } from '../../actions/actions'

class Search extends Component {

    render() {
        const {handleSubmit, "fields":{query}} = this.props;

        return (
            <div>
                <form onSubmit={handleSubmit(search)}>
                    <Field className='searchInput' name="query" component="input" type="text" placeholder="Enter course name"/>
                    <button className='searchSubmit' type='submit' >Search</button>
                </form>
            </div>
        );
    }
}
export default reduxForm({
    "form":"searchForm",
    "fields":["query"]
}, null, {search})(Search);

我的搜索操作是这样的

search : function(query){
    var data = {
        ep:"EP_SEARCH",
        payload:{
            query: query.query
        }
    }

    getAsynch(data).then(function(result){
        return {type: GET_DATA, payload:result};
    })
}

我收到来自端点的响应和结果,但我需要以某种方式分派操作。

我试过

getAsynch(data).then(function(result){
            return {type: GET_DATA, payload:result};
        })

这个

return function(dispatch){
    getAsynch(data).then(function(result){
        dispatch({type: GET_DATA, payload:result});
    })
}

但它会抛出一个错误,指出未定义分派。可能是因为我没有在组件中的任何地方传递它。

由于这是一个异步操作,因此您需要使用中间件来处理在不同时间分派多个操作。

操作创建者本质上是同步的,因此这就是为什么需要中间件以便将来在您的请求返回响应时分派同步操作的原因。

为了掌握,我建议您使用 redux-thunk,因为它比主要的替代 redux-promise 中间件库更容易掌握。

Redux Thunk 中间件

Redux Thunk middleware allows you to write action creators that return a function instead of an action.

首先在您的商店配置期间设置您的 redux-thunk 中间件

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

现在 redux-thunk 知道如何处理特殊 thunk 动作的调度

thunk 动作只是 return 另一个将 dispatch 作为参数的函数的动作。

Thunk 动作创作者

    function fetchThing(url) { 
        return (dispatch) => {
             /*dispatch more actions*/
        }
    }

这样做的好处是我们的组件可以像同步一样调度异步操作,不需要传递调度函数,因此不需要了解 Redux 存储。

redux-thunk 中间件知道在我们创建后立即拦截我们的 thunk 操作,并传入 dispatch 以便将来的操作(例如 RESPONSE_RECEIVED 操作)可以访问 dispatch。

为了使用 redux-thunk 创建一个 action creator,它 return 是一个函数,按照上面的方法接受 dispatch 作为参数。

例子

function epSearch(query){
    // thunk passes dispatch into the function below 
    // so that future actions will have access to dispatch

    return function(dispatch){

         // below function needs to return a promise in order for us to call .then
        getAsynch(data).then(   
          result => dispatch({ type: GET_DATA, payload:result }),
          error dispatch({ type: REQUEST_ERROR, payload: error })
        );
    };
}

如果 promise 由于错误而未解决,那么我们的 REQUEST_ERROR 操作将被分派,并且该操作的有效负载将是我们从被拒绝的 promise

中收到的错误

Redux Promise 和 Redux Thunk 的替代品

现在有其他方法可以控制异步数据流。然而,在我看来,redux-thunk 简单方便。 Redux Promise 是 Redux Thunk 的一个很好的替代品。这里的区别在于 redux-promise 是 拦截动作创建者的中间件 return promises 而不是 thunks。

但是严格来说,在 redux 中你根本不需要中间件来实现异步流。它的优点是数据流集中在一个地方,让你的组件更加解耦,因为它们不需要显式传递 Redux 的商店的调度方法,因此不关心 how 并创建动作。

有关 Redux 中中间件的深入讨论,请参阅 Dan Abramov 的 关于为什么我们需要中间件来实现 redux 中的异步流的问题,

我正在使用 Redux Thunk,我的操作对除 ReduxForm 之外的所有内容都有效。如果发现解决方案,请阅读大量有关该主题的内容。

search : function(query, dispatch){ //APPARENTLY DISPATCH IS THE SECOND PARAMETER, WHICH WAS MISSING IN MY INITIAL FUNCTION
        var data = {
            ep:"EP_SEARCH",
            payload:{
                query: query.query
            }
        }
        getAsynch(data).then((result)=>{
            dispatch({ type: GET_DATA, payload:result })
        });
    }

有关该主题的更多信息

onSubmit : Function [optional]

The function to call with the form data when the handleSubmit() is fired from within the form component. If you do not specify it as a prop here, you must pass it as a parameter to handleSubmit() inside your form component.

If your onSubmit function returns a promise, the submitting property will be set to true until the promise has been resolved or rejected. If it is rejected with a redux-form SubmissionError containing errors in the form { field1: 'error', field2: 'error' } then the submission errors will be added to each field (to the error prop) just like async validation errors are. If there is an error that is not specific to any field, but applicable to the entire form, you may pass that as if it were the error for a field called _error, and it will be given as the error prop.

onSubmit will be called with the following parameters:

values : Object

The field values in the form of { field1: 'value1', field2: 'value2' }.

dispatch : Function

The Redux dispatch function.

props : Object

The props passed into your decorated component.

http://redux-form.com/6.2.0/docs/api/ReduxForm.md/

TBH 我仍然不明白 dispatch 是如何进入 action creator 的,以及为什么我尝试过的之前的建议不起作用。最好能有更熟悉该主题的人发表评论。

TBH I still don't get how dispatch got inside the action creator and why the previous suggestions, which I tried, do not work. A comment from someone more familiar with the topic would be nice.

(抱歉,没有足够的代表发表评论)

redux-form 的 handleSubmit 似乎总是将 dispatch(派生自它自己的 props 参数)作为您提供的提交函数的第二个参数(参见 https://github.com/erikras/redux-form/blob/master/src/handleSubmit.js)

我假设这通常是 undefined,但是 thunk,如果存在,将使 dispatch 可用于 redux-form,因此也可用于您。