0
votes

i'm confuse in following tutorial on youtube.i pass two function as object into mapDispatchtoProps and the function like below,

import axios from 'axios'

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

and this is the second function or action creator,

import {ADD_FLASH_MESSAGE} from './types'

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

and now i pass them both in this file,

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)

and in the presentation component i use them,

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
}

i dont get it how it works in submit function, im still new in react especially redux, from what i learn in order to make inform or update state in store we have to dispatch and action, so in my head i figure something like this,

dispatch(this.props.addFlashMessage({action}), then the reducer do his job.

but how can this.props.addflashmessage can get dispatched while this.props.signuprequest(this.state) only returning a function with dispatch as parameter and return api call result.

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
"tutorial from youtube" ...Sainan
yes dude im confuse how it worksJsnow

2 Answers

1
votes

Simply because:

import {connect} from 'react-redux'

What this line does, is wrap all the actions you passed in with a dispatch and automatically dispatch them. Check the official docs for more in-depth understanding: http://redux.js.org/docs/basics/UsageWithReact.html

In this case, you have done

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

in Signup.jsx, so you don't need to mannaully dispatch them.

0
votes

What Stabley said is totally correct. I just want to add more details. basically, the connect is an HOC which is to add more functionality to your component.

The magic function is bindActionCreators, it will turn an object whose values are action creators, into an object with the same keys, but with every action creator wrapped into a dispatch call so they may be invoked directly.You can check more detailed documentation 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)

So inside the connect function it just called the bindActionCreators with the actions you passed to it.