I'm using Axios to perform a GET request and then store the information into the {information} property, and then I store all of that in my state. How can I use setState to set the state of the input fields after the compoenntDidMount()?? I've tried a .then() after the this.props.getItemCredential, but it doesn't work because it's not a standard fetch request?
I've also tried to set the state of the input value like: {this.state.profile.credential.itemArray[0].company} and it returns undefined even though I see it in my redux chrome extension as properly being in the state.
I think the issue is that it's returning undefined cause it cannot change the value of the input until the getItemCredential returns, but then how do I wait for it to finish and then adjust the: this.state.(whatever) for each one?
What my component looks like:
import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import TextFieldGroup from '../../common/TextFieldGroup';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getItemCredential, getCurrentProfile } from '../../../actions/profileActions';
import Spinner from '../../common/Spinner';
class EditInfo extends Component {
constructor(props) {
super(props);
this.state = {
company: '',
title: '',
location: '',
errors: {},
disabled: false
}
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
this.props.getItemCredential(this.props.match.params.id)
this.props.getCurrentProfile()
}
onChange = (e) => {
this.setState({[e.target.name]: e.target.value});
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({errors: nextProps.errors});
}
}
onSubmit = (e) => {
e.preventDefault();
const itemData = {
company: this.state.company,
title: this.state.title,
location: this.state.location,
}
}
render() {
const { errors } = this.state;
const { profile, loading } = this.props.profile;
const { credential } = this.props.profile;
let editContent;
if (profile === null || loading) {
editContent = <Spinner />
} else {
editContent = (
<React.Fragment>
<div>
<form onSubmit={this.onSubmit}>
<TextFieldGroup
placeholder={this.state.company}
name="company"
value={this.state.company}
onChange={this.onChange}
error={errors.company}
required
/>
<TextFieldGroup
placeholder="* Job Title"
name="title"
value={this.state.title}
onChange={this.onChange}
error={errors.title}
required
/>
<TextFieldGroup
placeholder="Location"
name="location"
value={this.state.location}
onChange={this.onChange}
error={errors.location}
required
/>
<div class="col-xl-4 col-lg-4 col-md-4 col-sm-12 text-center my-auto">
<input type="submit" value="Submit" class="button text-center m-auto add-credentials-button mt-4" />
</div>
</form>
</div>
);
}
return (
<div>
{editContent}
</div>
)
}
}
EditInfo.propTypes = {
profile: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
getItemCredential: PropTypes.func.isRequired,
getCurrentProfile: PropTypes.func.isRequired,
credential: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
profile: state.profile,
credential: state.credential,
errors: state.errors
});
export default connect(mapStateToProps, { addExperience, getExperienceCredential, getCurrentProfile })(withRouter(EditExperience));
Here is what my state markup looks like:
profile: {
credential: {
itemArray: [
0: {
title: 'Some entry',
company: 'Some entry',
Location: 'some entry'
}
]
}
}
Here is the axios request I'm making:
export const getItemCredential = (id) => dispatch => {
dispatch(setProfileLoading());
axios.get(`/profile/item-credential/${id}`)
.then(res =>
dispatch({
type: GET_ITEM_CREDENTIAL,
payload: res.data
})
)
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
}
Here is what my reducer looks like:
import { GET_PROFILE, PROFILE_LOADING, GET_ITEM_CREDENTIAL } from '../actions/types';
const initialState = {
profile: null,
credential: null,
loading: false
}
export default function(state = initialState, action) {
switch(action.type) {
case PROFILE_LOADING:
return {
...state,
loading: true
}
case GET_PROFILE:
return {
...state,
profile: action.payload,
loading: false
}
case GET_ITEM_CREDENTIAL:
return {
...state,
credential: action.payload
}
default:
return state;
}
}
You can do a .then if you change getItemCredential so it returns a Promise:
export const getItemCredential = (id) => dispatch => {
dispatch(setProfileLoading());
return axios.get(`/profile/item-credential/${id}`)
.then(res => {
dispatch({
type: GET_ITEM_CREDENTIAL,
payload: res.data
});
return res.data;
})
.catch(err => {
dispatch({
type: GET_ERRORS,
payload: err.response.data
});
throw err;
});
}
Notice the added return in getItemCredential. Also, notice that res.data is returned from the Promise so that it can be accessed by your component that awaits it. I also re-threw the caught error so that the Promise continues in the rejected state instead of resolving to undefined.
Related
I am using Redux with ReactJS. I also am utilizing devise-JWT for auth. Upon a refresh of the page, my state is changed and loggedIn becomes "false". I also get 400 Bad Request error upon posting data through fetch. I can login just fine and be redirected.
My user reducer:
import {
SIGNUP_USER,
LOGIN_USER,
LOGOUT_USER,
STORE_TOKEN
} from '../actions/types'
const INITIAL_STATE = {
loggedIn: false,
currentUser: {}
}
export default (state = INITIAL_STATE, action) => {
switch(action.type){
case SIGNUP_USER:
return {
...state,
loggedIn: true,
currentUser: action.payload
}
case LOGIN_USER:
return {
...state,
loggedIn: true,
currentUser: action.payload
}
case LOGOUT_USER:
return {
...state,
user: state.users.filter(user => user.id !== action.payload.id),
loggedIn: false
}
case STORE_TOKEN:
return {
token: action.payload.token,
}
default:
return state
}
}
My action:
export function loginUser(data){
return (dispatch) => {
fetch("http://localhost:3000/login", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user: {
...data
}
})
})
.then(resp => {
//debugger
if (resp.ok) {
resp.json().then(json => {
localStorage.setItem('token', json.token)
dispatch({ type: LOGIN_USER, payload: json })
})
}
})
}
}
My login component:
import React from 'react'
import TextField from '#material-ui/core/TextField'
import Button from '#material-ui/core/Button'
import { loginUser } from '../actions/index'
import { connect } from 'react-redux'
class Login extends React.Component {
state = {
email: '',
password: ''
}
handleSubmit = (e) =>{
e.preventDefault()
let credentials = this.state
this.props.loginUser(credentials)
this.props.history.push('/bookmarks')
}
handleChange = (e) => {
this.setState({[e.target.name]: e.target.value})
}
render() {
const { email, password } = this.state
return (
<div className="login-form">
<h1>Login</h1>
<form onSubmit={this.handleSubmit}>
<div>
<TextField type="text" name="email" placeholder="Email" onChange={this.handleChange} value={email} />
</div>
<div>
<TextField type="password" name="password" placeholder="Password" onChange={this.handleChange} value={password}/>
</div><br></br>
<Button type="submit" value="Login">Login</Button>
</form>
</div>
)
}
}
const mapDispatch = (dispatch) => {
return {
loginUser: (credentials) => dispatch(loginUser(credentials))
}
}
export default connect(null, mapDispatch)(Login)
I used devise-JWT for authentication.
You're logged out because the only place you store the credentials is in the redux store, which is (essentially) a variable.
When you refresh the page, you reinitialise the store to the default state.
You haven't stored the credentials anywhere where they would persist, such as local storage or a cookie.
I am trying to add new functionality in ready social networks to make it possible to edit published posts. But when I invoke getPost and addPostEdited functions from the EditPost react component, I have no result - none of these functions work and its actions do not dispatch. What important operation did I miss?
React component is here:
import React, { Fragment, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import Moment from 'react-moment';
import { connect } from 'react-redux';
import { deletePost, getPost, addPostEdited } from '../../actions/post';
const EditPost = ({
post: { _id, text, name, avatar, user, date }, match
}) => {
useEffect(() => {
getPost(match.params.id);
}, [getPost]);
const [newText, setText] = useState(text);
return (
<Fragment >
<Link to='/posts' className='btn'>
Back To Posts
</Link>
<div>
<Link to={`/profile/${user}`}>
<img className='round-img' src={avatar} alt="" />
<h4>{name}</h4>
</Link>
</div>
<div>
<form
className='form my-1'
onSubmit={e => {
e.preventDefault();
addPostEdited({ text }, _id);
setText('');
}}
>
<textarea
name='text'
cols='30'
rows='5'
placeholder='Edit the post'
value={newText}
onChange={e => setText(e.target.value)}
required
/>
<input type='submit' className='btn btn-dark my-1' value='Publish' />
</form>
<p className='post-date'>
Posted on <Moment format='YYYY/MM/DD'>{date}</Moment>
</p>
<Fragment>
<button
onClick={() => deletePost(_id)}
type='button'
className='btn btn-danger' >
<i className='fas fa-times' />
</button>
</Fragment>
</div>
</Fragment>
);
};
EditPost.propTypes = {
post: PropTypes.object.isRequired,
deletePost: PropTypes.func.isRequired,
getPost: PropTypes.func.isRequired,
addPostEdited: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
post: state.post
});
export default connect(mapStateToProps, { deletePost, getPost, addPostEdited })(EditPost);
File with actions:
import axios from 'axios';
import { setAlert } from './alert';
import {
GET_POSTS,
POST_ERROR,
ADD_POST,
GET_POST,
DELETE_POST,
ADD_COMMENT,
REMOVE_COMMENT,
UPDATE_LIKES,
EDIT_POST,
POST_EDITED
} from './types';
export const getPosts = () => async dispatch => {
try {
const res = await axios.get('api/posts');
dispatch({
type: GET_POSTS,
payload: res.data
});
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
export const addPostEdited = (formData, id) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
try {
const res = await axios.put(`/api/posts/${id}`, formData, config);
dispatch({
type: POST_EDITED,
payload: res.data
});
dispatch(setAlert('Post Edited', 'success'));
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
};
};
Reducer:
import {
GET_POSTS,
POST_ERROR,
UPDATE_LIKES,
DELETE_POST,
ADD_POST,
GET_POST,
ADD_COMMENT,
REMOVE_COMMENT,
EDIT_POST,
POST_EDITED
} from '../actions/types';
const initialState = {
posts: [],
post: null,
loading: true,
error: {}
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_POSTS:
return {
...state,
posts: payload,
loading: false,
};
case GET_POST:
case POST_EDITED:
return {
...state,
post: payload,
loading: false,
};
case EDIT_POST:
return {
...state,
post: payload,
loading: false,
};
case ADD_POST:
return {
...state,
posts: [payload, ...state.posts],
loading: false,
};
case DELETE_POST:
return {
...state,
posts: state.posts.filter(post => post._id !== payload),
loading: false
};
case POST_ERROR:
return {
...state,
error: payload,
loading: false
};
case UPDATE_LIKES:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id ? {...post, likes: payload.likes } : post
),
loading: false
};
case ADD_COMMENT:
return {
...state,
post: {...state.post, comments: payload },
loading: false
};
case REMOVE_COMMENT:
return {
...state,
post: {
...state.post,
comments: state.post.comments.filter(
comment => comment._id !== payload
)
},
loading: false
};
default:
return state;
}
};
You will have to receive deletePost, getPost, addPostEdited from the props.
Currently you are directly using it and not from props which is provided by connect.
I have set everything in Redux side and I see every action in Redux Devtool. It works all perfect. The problem occurs when I want to dispatch action in React Component. In login component I want to dispatch action, wait its response then depending on response redirect it to a page or show errors. Here are my codes:
userActions.js
import axios from "axios";
import {
LOGIN_USER,
LOGIN_USER_SUCCESS,
LOGIN_USER_FAILED,
} from "./types";
const loginUserRequest = () => {
return {
type: LOGIN_USER,
};
};
const loginUserSuccess = (user) => {
return {
type: LOGIN_USER_SUCCESS,
payload: user,
};
};
const loginUserFailed = (error) => {
return {
type: LOGIN_USER_FAILED,
payload: error,
};
};
export const loginUser = (dataSubmitted) => {
return (dispatch) => {
dispatch(loginUserRequest());
axios
.post("/api/users/login", dataSubmitted)
.then((response) => {
dispatch(loginUserSuccess(response.data));
})
.catch((err) => {
dispatch(loginUserFailed(err));
});
};
};
userReducer.js:
import {
LOGIN_USER,
LOGIN_USER_SUCCESS,
LOGIN_USER_FAILED,
} from "../actions/types";
const initialState = {
loading: false,
user: "",
error: "",
};
export default function (state = initialState, action) {
switch (action.type) {
case LOGIN_USER:
return { ...state, loading: true };
case LOGIN_USER_SUCCESS:
return { ...state, loading: false, user: action.payload, error: "" };
case LOGIN_USER_FAILED:
return { ...state, loading: false, user: "", error: action.payload };
default:
return state;
}
}
The above codes works great and does the job. The problem is in following code where I am dispatching the async action. After I run the code I get this.props.userData as undefined.
Login.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { loginUser } from "../../actions/userActions";
export class Login extends Component {
state = {
email: "",
password: "",
errors: [],
};
displayErrors = (errors) =>
errors.map((error, i) => (
<div className="alert alert-danger" key={i}>
{error}
</div>
));
handleSubmit = (e) => {
e.preventDefault();
var { email, password } = this.state;
var errors = [];
if (email === "") {
errors.push("Email is required");
}
if (password === "") {
errors.push("Password is required");
}
this.setState({ errors: errors });
//Problem occurs here
this.props.dispatch(loginUser({ email, password }));
if (response.payload.success) {
sessionStorage.setItem("jwt", response.payload.token);
sessionStorage.setItem("userId", response.payload._id);
this.props.history.push("/");
} else {
errors.push("Username and/or Password is not correct");
this.setState({ errors: errors });
}
};
render() {
return (
<form className="form-signin" onSubmit={this.handleSubmit}>
<h1 className="h3 mb-3 font-weight-normal">Sign in</h1>
{this.state.errors.length > 0 && this.displayErrors(this.state.errors)}
<label for="inputEmail" className="sr-only">
Email address
</label>
<input
type="email"
id="inputEmail"
className="form-control"
placeholder="Email address"
value={this.state.email}
onChange={(e) => {
this.setState({ email: e.target.value });
}}
required
autoFocus
/>
<label for="inputPassword" className="sr-only">
Password
</label>
<input
type="password"
id="inputPassword"
className="form-control"
placeholder="Password"
value={this.state.password}
onChange={(e) => {
this.setState({ password: e.target.value });
}}
required
/>
<div className="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> Remember me
</label>
</div>
<button
className="btn btn-lg btn-primary btn-block"
type="submit"
onClick={this.handleSubmit}
>
Sign in
</button>
<Link to="/register">Sign Up</Link>
</form>
);
}
}
function mapStateToProps(state) {
return {
userData: state.user,
};
}
export default connect(mapStateToProps)(Login);
You need to install connected-react-router to manipulate with a history inside redux:
import { push } from 'connected-react-router';
export const loginUser = (dataSubmitted) => {
return (dispatch) => {
dispatch(loginUserRequest());
axios
.post("/api/users/login", dataSubmitted)
.then((response) => {
dispatch(loginUserSuccess(response.data));
if (response.payload.success) {
sessionStorage.setItem("jwt", response.payload.token);
sessionStorage.setItem("userId", response.payload._id);
push("/");
} else {
errors.push("Username and/or Password is not correct");
}
})
.catch((err) => {
dispatch(loginUserFailed(err));
});
};
};
I am trying pass logged data from my redux actions to the front end but keep getting user.name of null or undefined.
This is the front end where I am simply trying to get user.name to appear so that it says Hi user.name(name of persons account).
import React, { Component } from "react";
import { NewPropertyForm, FormPageOne, FormPageTwo, FormPageThree,
FormPageFour } from "../../components/NewPropertyForm";
import { PropertyList } from "../../components/PropertyList";
import { Container, Button, Modal, ModalCard, ModalCardTitle,
ModalBackground, ModalCardFooter, ModalCardHeader, Delete, ModalCardBody
} from 'bloomer';
import StepZilla from "react-stepzilla";
import modal from "./modal-bg.svg";
import "./Manager.css";
import {login} from '../../actions/authActions'
import {connect} from 'react-redux';
import { bindActionCreators } from 'redux'
const steps =
[
{name: 'Step 1', component: <FormPageOne /> },
{name: 'Step 2', component: <FormPageTwo /> },
{name: 'Step 3', component: <FormPageThree /> },
{name: 'Step 4', component: <FormPageFour /> }
]
const modalBG = { backgroundImage: `url(${modal})` }
export class Manager extends Component {
// Setting our component's initial state
state = {
modal: "",
};
modalOpen = () => {
this.setState({ modal: "is-active" })
}
modalClose = () => {
this.setState({
modal: "",
login: "",
})
}
render() {
let { user } = this.props;
return (
<div className="manager">
<Container className="manager-container">
<div className="columns">
<div className="column">
<h1 className="title">Hi {user.name}</h1>
<h2 className="sub-title">You currently have 3 properties</h2>
<h2 className="sub-title">Check out the new applications you
received.</h2>
</div>
<div className="column user-dash-right">
<Button
isColor='primary'
className=""
onClick={this.modalOpen}><p>Create Listing</p></Button>
</div>
</div>
<h1 className="title has-text-centered">My Properties</h1>
<PropertyList />
<div className="new-property-modal">
<Modal className={this.state.modal}>
<ModalBackground />
<ModalCard style={ modalBG } >
<ModalCardBody>
<Delete onClick={this.modalClose} />
<div className='step-progress'>
<StepZilla
steps={steps}
showSteps={false}
nextButtonCls="button is-medium is-primary"
backButtonCls="button is-medium is-primary"
/>
</div>
</ModalCardBody>
</ModalCard>
</Modal>
</div>
</Container>
</div>
);
}
}
const mapStateToProps = ({auth}) => ({
user: auth.user,
authError: auth.authError
});
export default connect(mapStateToProps)(Manager)
This is the actions I have setup
import API from "../utils/API";
import { IS_AUTHENTICATED, AUTHENTICATION_FAILED } from
'../constants/actionTypes';
export const signup = ({name, email, phonenumber, password, role}) =>
async dispatch => {
try {
const {data} = await API.saveUser({
name,
email,
phonenumber,
password,
role
})
dispatch({
type: IS_AUTHENTICATED,
payload: data.user
})
console.log('--success', data);
} catch(error) {
console.error(error);
console.log('Come on work damnit')
}
}
export const login = ({email, password}) => async dispatch => {
try {
const {data} = await API.loginUser({
email,
password
})
dispatch({
type: IS_AUTHENTICATED,
payload: data.user
});
console.log('--success', data.user.name);
} catch(error) {
dispatch({
type: AUTHENTICATION_FAILED,
payload: "Invalid credentials, cannot login"
});
console.error(error);
}
}
export const getAuthenticated = () => async dispatch => {
try {
const {data, error} = await API.getAuthenticated();
console.log(data);
if(data) {
dispatch({
type: IS_AUTHENTICATED,
payload: data
});
} else {
console.log('ssss', error)
}
// if(getUser) login
//else logout
} catch(error) {
//window redirect to login
}
}
export const logout = () => async dispatch => {
try {
// const revoke = await API.logout()
dispatch({
type: IS_AUTHENTICATED,
payload: null
});
//should automatically display logout nav
//or redirect to anther page
} catch(e) {
//just refresh page
}
}
and these are my reducers
import {
IS_AUTHENTICATED,
AUTHENTICATION_FAILED
} from '../constants/actionTypes';
const initialState = {
user: null
}
const authReducer = (state = initialState, {type, payload}) => {
switch(type) {
case IS_AUTHENTICATED:
return {...state, user: payload, userInfo: payload}
case AUTHENTICATION_FAILED:
return {...state, user: null, authError: payload}
default:
return state
}
}
export default authReducer;
As you can see I tried to pass user.name but i keep getting cannot read property of null if I do const { user } = this.props
and i get cannot read property of undefined if i do const { user } = this.state.
I figured it out i justed needed to add
<span>
<h1 className="title">Hi {user.name}</h1>
</span>
and it worked!
I was driven crazy by my first react-redux app. My Redux State is never updated.
I tried to find every solution on the website but they are not helping. One very similar question here used promise but I am not.
Redux-dev-tools catch the actions about the login_success but the global state is never updated, please tell me what should I do to debug if you could, thank you so much.
First Index.js
import ... from ...
const compostEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const rootReducer = combineReducers({
auth: authReducer,
})
const store = createStore(rootReducer, compostEnhancer(
applyMiddleware(thunk)
));
const app = (<BrowserRouter><App /></BrowserRouter>)
ReactDOM.render(<Provider store={store}>{app}</Provider>, document.getElementById('root'));
registerServiceWorker();
authReducer.js :
import * as actionTypes from '../actions/actionTypes';
const initialState = {
token: null,
userId: null,
error: null,
loading: false
}
const authReducer = (state = initialState, action) => {
switch (action.types) {
case actionTypes.LOGIN_START:
return {
...state,
};
case actionTypes.LOGIN_SUCCESS:
return {
...state,
token: action.idToken,
userId: action.userId,
loading: false,
error:null
}
default:
return state;
}
}
export default authReducer;
authAction.js:
import * as actionTypes from './actionTypes';
import axios from 'axios';
export const loginStart= () =>{
return {
type: actionTypes.LOGIN_START
};
}
export const loginSuccess = (token,userId) =>{
return {
type: actionTypes.LOGIN_SUCCESS,
userId: userId,
idtoken: token,
}
}
export const loginFail = (error) =>{
return {
type:actionTypes.LOGIN_FAIL,
error:error
}
}
export const auth = (email,password,isSignup ) =>{
return dispatch =>{
dispatch(loginStart());
const authData = {
email: email,
password: password,
returnSecureToken:true
}
let url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=...'
if(!isSignup ){
url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=...'
}
axios.post(url, authData)
.then( response =>{
console.log(response);
dispatch(loginSuccess(response.data.idToken, response.data.localId))
})
.catch(err=>{
console.log(err);
dispatch(loginFail(err));
})
}
}
Login.js (Component):
import ... from ...;
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
isSignup: false,
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = e => {
e.preventDefault();
// This will trigger actions
this.props.onAuth(this.state.email, this.state.password, this.state.isSignup);
console.log(this.props.token) //here I can Get Token
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
render() {
let form =
<div className={classes.ContactData} >
<h4>Sign IN</h4>
<form onSubmit={this.handleSubmit} >
<Input
elementType='input'
name="email"
required
label="Email"
placeholder="Email"
value={this.state.email}
margin="normal"
onChange={this.handleChange}
/>
<br />
<Input
elementType='input'
required
name="password"
value={this.state.password}
label="Password"
onChange={this.handleChange}
/>
<br />
<Button
color="primary"
type="submit"
>Submit</Button>
<Button color="primary" href="/"> CANCLE</Button>
</form>
</div>
if (this.props.loading) {
form = <Spinner />
}
let errorMessage = null;
if (this.props.error) {
errorMessage =(
<p>{this.props.error.message} </p>
)
}
let token = null;
if(this.props.token){
token = this.props.token.toString()
}
return (
<div>
{errorMessage}
{ form }
</div>
)
}
}
const mapStateToProps = state => {
return {
loading: state.auth.loading,
error: state.auth.error,
token:state.auth.idToken,
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (email, password, isSignup) => dispatch(actions.auth(email, password, isSignup)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
And also, the problem leads to my Spinner and show ErrorMessage not working.
I suppose its a typo.
instead of
switch (action.types)
try this
switch (action.type)
In reducer, we get an object returned from the actions, on the argument action.