Nitesh Nitesh - 6 days ago 5
React JSX Question

How to dispatch actions from Child components three level down?

I am currently facing this issue designing a React application and I don't seem to be able to find an answer to it.

So my application has following heirarchy of Components in React Router

App
-> DynamicContainer
-> -> LoginComponent

Now, LoginComponents has form elements to take username and password.

I have userActionCreators where the login is handled, and it dispatches login successful when finished, but I don't seem to be able find the right way to connect my LoginComponent to dispatch actions or call actionCreators.

How do I do it? Any suggestion would be appreciated.

Answer

One option is to bind your single-purpose forms to their actions with connect. Since <LoginComponent /> is typically always doing the exact same thing, you can use it like this:

import React from 'react';
import * as userActionCreators from '../actions/users';
import { connect } from 'react-redux';

export class LoginComponent extends React.Component {
   static propTypes = {
     login: React.PropTypes.func.isRequired
   }

   render() { 
     const { login } = this.props;
     const { username, password } = this.state;

     return (
       <form onSubmit={ () => login(username, password) }>
         ...
       </form>
     );
   }
}

export default connect(null, userActionCreators)(LoginComponent);

connect automatically binds the action creator and separately provides dispatch to props, so if you want to be more explicit, the above example is the same as

import React from 'react';
import { login } from '../actions/users';
import { connect } from 'react-redux';

export class LoginComponent extends React.Component {
   static propTypes = {
     dispatch: React.PropTypes.func.isRequired
   }

   render() { 
     const { login, dispatch } = this.props;
     const { username, password } = this.state;

     return (
       <form onSubmit={ () => dispatch(login(username, password)) }>
         ...
       </form>
     );
   }
}

export default connect()(LoginComponent);

And for reference, userActionCreators:

const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
const LOGIN_FAILED = 'LOGIN_FAILED';

export function login(username, password) {
  if (username === 'realUser' && password === 'secretPassword') {
    return { type: LOGIN_SUCCESS, payload: { name: 'Joe', username: 'realUser' } };
  } else {
    return { type: LOGIN_FAILED, error: 'Invalid username or password };
  }
}
Comments