调度动作创建者语法react-redux

时间:2016-10-19 05:56:41

标签: javascript reactjs ecmascript-6 redux react-redux

我在youtube上将以下教程混淆。我将两个函数作为对象传递给mapDispatchtoProps,函数如下,

import axios from 'axios'

export default (userdata) => {
    return dispatch => {
        return axios.post('/api/users', userdata);
    }
}

这是第二个功能或动作创建者,

import {ADD_FLASH_MESSAGE} from './types'

    export function addFlashMessage(message)
    {
        return{
            type:ADD_FLASH_MESSAGE,
            message
        }
    }

现在我在这个文件中传递它们,

import React from 'react'
import SignupForm from '../signup/SignupForm'
import {connect} from 'react-redux'
import signupRequest from './signupRequest'
import {addFlashMessage} from '../../actions/addFlashMessage'

class Signup extends React.Component {
    render() {
        const {signupRequest,addFlashMessage} = this.props;

        return (
            <div className="row">
            <div className="col-md-4 col-md-offset-4">
            <SignupForm signupRequest={signupRequest} addFlashMessage={addFlashMessage}/>
            </div>
            </div>
            )
    }
}

Signup.propTypes = {
    signupRequest: React.PropTypes.func.isRequired,
    addFlashMessage:React.PropTypes.func.isRequired
}

export default connect(null, {signupRequest,addFlashMessage})(Signup)

并在演示组件中使用它们,

import React from 'react'
import classname from 'classnames'
import {browserHistory} from 'react-router'
import validateInput from '../../../server/shared/validateInput'
import TextFieldGroup from  '../fieldgroup/textFieldGroup'

export default class SignupForm extends React.Component {
    constructor(props){
        super(props);
        this.state ={
            username: "",
            password: "",
            passwordConfirmation: "",
            email: "",
            errors:{},
            isLoading:false
        }
    }
    onChange(e){
        this.setState(
        {
            [e.target.name] : e.target.value

        })
    }

    isValid(){
        const {errors,isValid} =validateInput(this.state)
        if(!isValid){
            this.setState({errors});
        }
        return isValid;
    }

    onSubmit(e){
        e.preventDefault();
        if(this.isValid()){
            this.setState({
                errors:{},
                isLoading:true
            });
            this.props.signupRequest(this.state).then(
                () => {
                    this.props.addFlashMessage({
                        type:'success',
                        text:'Sign up successfull, Welcome aboard!'
                    });
                    browserHistory.push('/');
                }, ({data}) => this.setState({errors:data,isLoading:false}));
        }
    }

    render(){
        const {errors} = this.state;
        return (
            <form onSubmit={this.onSubmit.bind(this)}>
            <h1>Sign Up For Free</h1>   
            <TextFieldGroup
            error={errors.username} 
            label="Username"
            value={this.state.username}
            onChange={this.onChange.bind(this)}
            field="username"
            />
            <TextFieldGroup
            error={errors.email} label="Email"
            value={this.state.email} onChange={this.onChange.bind(this)}
            field="email" 
            />
            <TextFieldGroup
            error={errors.password} label="Password"
            value={this.state.password} onChange={this.onChange.bind(this)}
            field="password" type="password"/>
            <TextFieldGroup
            error={errors.passwordConfirmation} label="Password Confirmation"
            value={this.state.passwordConfirmation} onChange={this.onChange.bind(this)}
            field="passwordConfirmation" type="password" />
            <div className="form-group">
            <button disabled={this.state.isLoading} className="btn btn-primary btn-lg">
            Sign Up
            </button>
            </div>
            </form>
            )
    }

}

SignupForm.propTypes = {
    signupRequest: React.PropTypes.func.isRequired,
    addFlashMessage: React.PropTypes.func.isRequired
}

我不知道它如何在提交功能,我还是新的反应特别是redux,从我学到的知识,以便在商店通知或更新状态我们必须派遣和行动,所以在我脑海里我想到的东西像这样,

dispatch(this.props.addFlashMessage({action}),然后reducer完成他的工作。

但是如果this.props.addflashmessage只返回一个带有dispatch as参数的函数并返回api调用结果,this.props.signuprequest(this.state)如何调度。

this.props.signupRequest(this.state).then(
                () => {
                    this.props.addFlashMessage({
                        type:'success',
                        text:'Sign up successfull, Welcome aboard!'
                    });
                    browserHistory.push('/');
                }, ({data}) => this.setState({errors:data,isLoading:false}));

2 个答案:

答案 0 :(得分:1)

仅仅因为:

import {connect} from 'react-redux'

这一行的作用是用dispatch包装你传递的所有动作并自动发送它们。查看官方文档以获得更深入的了解:http://redux.js.org/docs/basics/UsageWithReact.html

在这种情况下,你已经完成了

export default connect(null, {signupRequest,addFlashMessage})(Signup)

在Signup.jsx中,所以你不需要动态地发送它们。

答案 1 :(得分:0)

Stabley说的是完全正确的。我只想添加更多细节。基本上,connect是一个HOC,它将为您的组件添加更多功能。

magic函数是bindActionCreators,它将一个值为动作创建者的对象转换为具有相同键的对象,但每个动作创建者都包含在一个调度调用中,因此可以直接调用它们。您可以查看更详细的信息。文档here.

wrapActionCreators.js

import { bindActionCreators } from 'redux'

export default function wrapActionCreators(actionCreators) {
return dispatch => bindActionCreators(actionCreators, dispatch)
}

connect.js

mapDispatch = wrapActionCreators(mapDispatchToProps)
const mappedDispatch = mapDispatch(store.dispatch, props)

因此在connect函数中,它只是使用您传递给它的动作调用bindActionCreators。