синтаксис диспетчерского действия, создающего react-redux

#javascript #reactjs #ecmascript-6 #redux #react-redux

#javascript #reactjs #ecmascript-6 #сокращение #реагировать-сокращение

Вопрос:

я запутался в следующем руководстве на 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
}
  

я не понимаю, как это работает в функции отправки, я все еще новичок в react, особенно redux, из того, что я узнал, чтобы сообщить или обновить состояние в хранилище, мы должны отправлять и действовать, поэтому в моей голове я представляю что-то вроде этого,

отправка (this.props.addFlashMessage({действие})), затем редуктор выполняет свою работу.

но как this.props.addflashmessage может быть отправлено, this.props.signuprequest(this.state) возвращая только функцию с отправкой в качестве параметра и возвращая результат вызова API.

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

Комментарии:

1. «учебное пособие с YouTube»…

2. да, чувак, я не понимаю, как это работает

Ответ №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. итак, всякий раз, когда я вызываю создателя действия addFlashMessage, он немедленно отправляется?

2. @Jsnow Правильно. Чтобы быть более точным, всякий раз, когда вы вызываете this.props.addFlashMessage (некоторые параметры)

3. @Jsnow Хотите принять ответ, если это то, что вам нужно?

Ответ №2:

То, что сказал Стабли, абсолютно верно. Я просто хочу добавить больше деталей. по сути, подключение является специальным, которое должно добавить больше функциональности вашему компоненту.

Волшебная функция — bindActionCreators , она превратит объект, значениями которого являются создатели действий, в объект с теми же ключами, но с каждым создателем действия, обернутым в вызов отправки, чтобы их можно было вызывать напрямую.Вы можете ознакомиться с более подробной документацией здесь.

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 с действиями, которые вы ему передали.