Reputation: 1
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
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