Nagavalli
Nagavalli

Reputation: 1

unable to bind actions to component React Redux

I am unable to bind actions to this component, I am using redux to bind actions, state of the component I am getting undefined, please help me thanks in advance.

actions and store and reducer I added below is the component, Action, reducer

        import React from 'react';
        import { Formik, Field, Form, ErrorMessage } from 'formik';
        import { bindActionCreators } from 'redux'
        import * as Yup from 'yup';
        import { connect } from "react-redux";
        import * as Actions from '../_actions'


        //import { userActions } from '../_actions';

        import { authenticationService } from '../_services';


        export class LoginPage extends React.Component {

            constructor(props) {

                super(props);

                // redirect to home if already logged in
                if (authenticationService.currentUserValue) {
                    this.props.history.push('/');
                }
            }

            render() {
                return (
                    <div>
                        <div className="alert alert-info">
                            <strong>Normal User</strong> - U: user P: user<br />
                            <strong>Administrator</strong> - U: admin P: admin
                        </div>
                        <h2>Login</h2>
                        <Formik
                            initialValues={{
                                username: '',
                                password: ''
                            }}
                            validationSchema={Yup.object().shape({
                                username: Yup.string().required('Username is required'),
                                password: Yup.string().required('Password is required')
                            })}
                            onSubmit={((obj) => this.props.Actions.login(obj.username, obj.password))}

                            render={({ errors, status, touched, isSubmitting }) => (
                                <Form>
                                    <div className="form-group">
                                        <label htmlFor="username">Username</label>
                                        <Field name="username" type="text" className={'form-control' + (errors.username && touched.username ? ' is-invalid' : '')} />
                                        <ErrorMessage name="username" component="div" className="invalid-feedback" />
                                    </div>
                                    <div className="form-group">
                                        <label htmlFor="password">Password</label>
                                        <Field name="password" type="password" className={'form-control' + (errors.password && touched.password ? ' is-invalid' : '')} />
                                        <ErrorMessage name="password" component="div" className="invalid-feedback" />
                                    </div>
                                    <div className="form-group">
                                        <button type="submit" className="btn btn-primary" disabled={isSubmitting}>Login</button>
                                        {isSubmitting &&
                                            <img src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
                                                alt="login" />
                                        }
                                    </div>
                                    {status &&
                                        <div className={'alert alert-danger'}>{status}</div>
                                    }
                                </Form>
                            )}
                        />
                    </div>
                )
            }
        }
        function mapDispatch(dispatch) {
            return bindActionCreators({ Actions }, dispatch)
        }
        function mapStateProps(props) {
            return {
                allprop: props
            }
        }

        connect(mapStateProps, mapDispatch)(LoginPage); 

action I have index.js file so I am adding action main code

    import { authenticationConstants } from '../_constants';
    import { authenticationService } from '../_services';
    import { history } from '../_helpers';
    import{alertActions} from './alert.actions'

    export const userActions = {
        login,
        logout,
        getAll,
    };

    function login(username, password) {
        return dispatch => {
            dispatch(request({ username }));

            authenticationService.login(username, password)
                .then(
                    user => { 
                        dispatch(success(user));
                        history.push('/');
                    },
                    error => {
                        dispatch(failure(error));
                        dispatch(alertActions.error(error));
                    }
                );
        };

        function request(user) { return { type: authenticationConstants.LOGIN_REQUEST, user } }
        function success(user) { return { type: authenticationConstants.LOGIN_SUCCESS, user } }
        function failure(error) { return { type: authenticationConstants.LOGIN_FAILURE, error } }
    }

    function logout() {
        authenticationService.logout();
        return { type: authenticationConstants.LOGOUT };
    }

    function getAll() {
        return dispatch => {
            dispatch(request());

            authenticationService.getAll()
                .then(
                    users => dispatch(success(users)),
                    error => dispatch(failure(error))
                );
        };

        function request() { return { type: authenticationConstants.GETALL_REQUEST } }
        function success(users) { return { type: authenticationConstants.GETALL_SUCCESS, users } }
        function failure(error) { return { type: authenticationConstants.GETALL_FAILURE, error } }
    }

I am adding reducer, please go through it

import { authenticationConstants } from '../_constants';

let user = JSON.parse(localStorage.getItem('user'));
const initialState = user ? { loggedIn: true, user } : {};

export function authentication(state = initialState, action) {
  switch (action.type) {
    case authenticationConstants.LOGIN_REQUEST:
      return {
        loggingIn: true,
        user: action.user
      };
    case authenticationConstants.LOGIN_SUCCESS:
      return {
        loggedIn: true,
        user: action.user
      };
    case authenticationConstants.LOGIN_FAILURE:
      return {};
    case authenticationConstants.LOGOUT:
      return {};
    case authenticationConstants.GETALL_REQUEST:
      return {
        loading: true
      };
    case authenticationConstants.GETALL_SUCCESS:
      return {
        items: action.users
      };
    case authenticationConstants.GETALL_FAILURE:
      return {
        error: action.error
      };
    default:
      return state
  }
}

Upvotes: 0

Views: 175

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281894

You must pass Actions as the first argument to bindActionCreators instead of as an object

 function mapDispatch(dispatch) {
        return bindActionCreators(Actions, dispatch)
 }

and then use the action like

this.props.login(obj.username, obj.password);

However you can simply use an object as the second argument instead using bindActionCreators like

connect(mapStateProps, Actions)(LoginPage);

Also you must export and use the connected component instead of exporting the normal component

So instead of this

export class LoginPage extends React.Component {

You should have

class LoginPage extends React.Component {
....

const LoginPageWithConnect = connect(mapStateProps, Actions)(LoginPage);
export { LoginPageWithConnect as LoginPage };

Upvotes: 0

Related Questions