Set Input Value based on React State after componentDidMount? - javascript

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

Upon refresh of the page, I am logged out? Why?

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.

Why cannot I invoke action to dispatch?

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.

How to dispatch async action in Redux using Redux Thunk: TypeError: Cannot read property 'loading' of undefined

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));
});
};
};

Im am getting undefined with mapstatetoprops

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!

React Reducer is not updating State

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.

Categories