Search code examples
reduxreact-reduxredux-formredux-thunkreact-router-redux

dispatch a action once server side validation passed in redux form


I have facing a problem in redux form , my issue is in code, once i pass my server validation. I want to dispatch a action, but i couldn't make it, i am using redux form's submit validations example approach, in my form i have both the client & server side validation.

LoginForm.js

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

import { required, email, maxLength25 } from '../utils/validations';
import validate from '../utils/signup_validate';
import { renderField } from '../utils/textFieldGroup';
import { login } from '../actions/submit';

const LoginForm =(props) => {
        const { handleSubmit, submitSucceeded, error } = props

        return (
          <form onSubmit={handleSubmit(login)}>
            <div className={typeof error!='undefined'?'show alert alert-danger': 'hidden'}>
             <strong>Error!</strong> {error}
            </div>
            <Field name="email" type="text"
              component={renderField} label="Email"
              validate={[ required, email, maxLength25 ]}
            />
            <Field name="password" type="password"
              component={renderField} label="Password"
              validate={[ required, maxLength25 ]}
            />
            <p>
              <button type="submit" disabled={submitSucceeded} className="btn btn-primary btn-lg">Submit</button>
            </p>
          </form>
        )
}

export default reduxForm({
  form: 'loginForm', // a unique identifier for this form
  validate
})(LoginForm)

submit.js

import axios from 'axios';
import isEmpty from 'lodash/isEmpty';
import { SubmissionError } from 'redux-form'
import {browserHistory} from 'react-router';
import setAuthorizationsToken from '../utils/setAuthorizationsToken';
import { SET_CURRENT_USER } from '../utils/types';
import jwt from 'jsonwebtoken';

export function login(data){
    console.log('submit', data);
    return axios.post('api/auth/login', data)
    .then((response) => {
        console.log('response', response.data.token);
        const token = response.data.token
        localStorage.setItem('jwtToken', token)
        setAuthorizationsToken(token)
        store.dispatch(setCurrentUser(jwt.decode(localStorage.jwtToken)))
        browserHistory.push('/');
    })
    .catch((error) => {
        console.log('error', error.response);
        throw new SubmissionError({ _error: error.response.data.errors});
    })
}

function setCurrentUser(user) {
    console.log('setCurrentUser');
    return {
        type: SET_CURRENT_USER,
        user: user
    }
}

i want to dispatch the setCurrentUser function so that i can set the user data in redux store.

Thanks in advance.


Solution

  • Solution 1

    Instead of passing directly your login function to the handleSubmit, you can pass anonther function that does:

    login(data).then((user) => dispatch(setCurrentUser(user))
    

    For this to work, you need to use connect from react-redux to allow your component access to the dispatch function of the redux store. Also, you need to return the user from the resolve branch of the ajax call:

    .then((response) => {
        console.log('response', response.data.token);
        const token = response.data.token
        localStorage.setItem('jwtToken', token)
        setAuthorizationsToken(token)
        return jwt.decode(localStorage.jwtToken));
    })
    

    Also, my advice is to move the browserHistory.push('/') call to the component (after dispatching the setCurrentUser action)

    Solution 2

    You actually need to chain actions together, login -> then -> setCurrentUser. For this you should use a redux middleware. If you haven't worked with middlewares before I suggest starting with redux-thunk: https://github.com/gaearon/redux-thunk. With redux-thunk you can use the dispatch function inside your action creators to dispatch multiple actions. If you want more info on this, drop a comment below and I'll try to expand my answer.