'Why user data is null in props in React Js?
I create multi step register that user create in first step and then send OTP code in last step user set username and password. In last step when I use props show me user is null but in react dev tools user already exist. This Two picture:
This is my reduser code :
import {
USER_LOADED,
USER_LOADING,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGOUT_SUCCESS,
REGISTER_SUCCESS,
REGISTER_FAIL,
VERIFY_CODE,
SET_PASS,
SET_PASS_FAIL,
VERIFY_FAIL
} from "../actions/types";
const initialState = {
token: localStorage.getItem("token"),
isAuthenticated: null,
isLoading: false,
verifyCode : null,
setPass : null,
user: null,
};
export default function (state = initialState, action) {
switch (action.type) {
case USER_LOADING:
return {
...state,
isLoading: true,
};
case USER_LOADED:
return {
...state,
isAuthenticated: true,
isLoading: false,
verifyCode: true,
user: action.payload,
};
case LOGIN_SUCCESS:
case REGISTER_SUCCESS:
localStorage.setItem("token", action.payload.token);
return {
...state,
...action.payload,
isAuthenticated: true,
isLoading: false,
verifyCode: false
};
case SET_PASS_FAIL:
case AUTH_ERROR:
case LOGIN_FAIL:
case VERIFY_FAIL:
return {
...state,
verifyCode: false,
isLoading: true
}
case VERIFY_CODE :
return {
...state,
user: action.payload,
verifyCode: true,
isAuthenticated: true,
isLoading: false
};
case SET_PASS :
return {
...state,
user: action.payload,
isAuthenticated: true,
isLoading: false,
setPass: true,
}
case LOGOUT_SUCCESS:
localStorage.removeItem("token");
return {
token: null,
user : null,
isAuthenticated: false,
isLoading: true
}
case REGISTER_FAIL:
localStorage.removeItem("token");
return {
...state,
token: null,
user: null,
isAuthenticated: false,
isLoading: false,
};
default:
return state;
}
}
In last step user fill username and password and we need pass email too. And this my component code :
import React, {Component} from "react";
import PropTypes from "prop-types";
import {loadUser, setPass, verifyCode , browserHistory} from "../../actions/authAction";
import {connect} from "react-redux";
import {clearError} from "../../actions/errorAction";
import {toast} from "react-toastify";
import store from "../../store";
class RegisterFinal extends Component {
constructor(props) {
super(props);
this.state = {
email: this.props.auth,
}
}
componentDidMount() {
store.dispatch(loadUser());
}
state = {
user : [],
userName : "",
password : "",
verifyCode : "",
passwordConfirm : "",
isLoading: true,
msg: null
}
static propTypes = {
isAuthenticated : PropTypes.bool,
setPass : PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
};
componentDidUpdate(prevProps) {
const {error} = this.props;
if (error !== prevProps.error) {
if (error.id === 'SET_PASS_FAIL') {
let status =error.status;
if (status === 400) {
toast.error("کاربر موجود است")
}
} else {
this.setState({msg: null});
}
}
}
onSubmit = (e) => {
e.preventDefault();
const {password , userName , verifyCode} = this.state
const setPass = {
password , userName , verifyCode
}
this.props.setPass(setPass);
const { passwordConfirm } = e.target;
const errors = {};
if (password.value !== passwordConfirm.value) {
errors.passwordMismatch = "Entered passwords do not match.";
console.log(errors)
}}
onChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
const {user} = this.state;
return (
<div className={"container"}>
<div className={"row row-of-final-register justify-content-center"}>
<div className={"mt-5 register-teacher-inputs-box final-register-teacher-inputs-box"}>
<div className={"final-register-wrapper"}>
<div className={"register-teacher-icon final-register-teacher-icon"}>
</div>
<div className={"register-teacher-text final-register-teacher-text"}>
<h4>
Last Step
</h4>
<p>
Account
</p>
</div>
</div>
<form className={"mt-5"} onSubmit={this.onSubmit}>
<div className={"row"}>
<div className={"col-12"}>
<label
htmlFor={"userName"} className={"text-right username-label"}>
<span>*</span>
</label>
<input type="text" className="form-control w-100" placeholder={"username"}
name={"userName"}
autoComplete="true"
value={this.userName}
onChange={this.onChange}
onFocus={(e) => e.target.placeholder = ""}
/>
</div>
</div>
<div className={"row"}>
<div className={"col-12 col-lg-6 mt-3"}>
<label
htmlFor={"password"} className={" text-right"}>
<span>*</span>
</label>
<input type="password" className="form-control " placeholder={"Password"}
name={"password"}
value={this.password}
onChange={this.onChange}
onFocus={(e) => e.target.placeholder = ""}
/>
</div>
</div>
<div className={"row mt-3 pt-2"}>
<div className={"col-12 final-register-wrapper final-register-btn"}>
<button type={"submit"} className={"final-register-btn"}>Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
)
}
}
const mapStateToProps = (state) => ({
setPass : state.setPass,
isAuthenticated : state.isAuthenticated,
error : state.error,
auth: state.auth,
});
export default connect(mapStateToProps , {
setPass , clearError ,loadUser
})(RegisterFinal);
Solution 1:[1]
// First of all, I would change this,
// is not a good idea import your store to each component.
import store from '../store';
...
componentDidMount() {
store.dispatch(loadUser());
}
// and I would do this
import { loadUser as loadUserAction } from '../actions';
...
componentDidMount() {
this.props.loadUser();
}
...
...
const mapDispatchToProps = (dispatch) => ({
loadUser: () => dispatch(loadUserAction()),
setPass: () => dispatch(setPassAction()),
clearError: () => dispatch(clearErrorAction()),
});
export default connect(mapStateToProps, mapDispatchToProps)(RegisterFinal);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | guiwme5 |