I'm new to react
and redux
and have been exploring how it is different from angular
.
I'm trying to do a simple login page and am not able to achieve what I want. Once I get the username and password from a login form, I submit it like below :
submitHandler(e){
e.preventDefault();
var user = {
name : this.state.username,
password: this.state.password
}
this.props.authenticateUser(user);
browserHistory.push('/home');
this.setState({
username:'',
password:''
})
}
Here, authenticateUser
is a function inside my reducer (shown below) which checks from an already existing user's list and then the state with a property isAuthenticated
:
case 'AUTHENTICATE_USER':
var users = state.userslist;
var payloadUser = action.payload;
for (let i = 0; i < users.length; i++) {
let user = users[i]
if (user.name === payloadUser.name) {
return {...state, isAuthenticated: true };
}
};
return {...state, isAuthenticated: false };
Now in Angular, I would just wait for this call to finish and check whether this value is true
or false
, and navigate to the home page using angular-router
.
But how would I achieve the same in react
. I am using react-router
in my sample application.
I tried to check isAuthenticated
in my submitHandler
function right below where I call this.props.authenticateUser(user)
, but the problem is , this.props.isAuthenticateUser
is not updated and returns false
, which I have set as the initialState
in my reducer.
Please tell me how I can check isAuthenticated
after the authenticateUser
function has called so that I can proceed with my homepage routing. Do I have to use a promise
and wait for the state to be updated by redux
and then check it again ?? (I know react is a one way path and it doesn't work that way.)
Also if my authentication fails, how do I show an error panel below my login form. I think using a component for the error panel which takes in isAuthenticated
as input and checking if false in order to show (ie. ngShow like in Angular.) But I'm afraid that will not work as well, since my state will not be updated just in time.
I know that the render function will be called with any change in state. But I just can't wrap my head around React clearly.
Edit: For brevity, I have not provided the action creators and the full reducer above rather shown only the switch case operation for authenticate user. My app follows the original redux architecture with actions, reducers, containers, components and such.
EDIT: Github link here
I will try to explain briefly how data flow works in a Redux application:
The reducer should not be called directly from the component. Your call to authenticate user should be inside an action and that is what should be dispatched from the component.
When you define the action, you can give a property to define the type of action it is. For example, in this case, it could be type: AUTHENTICATE_USER
After the completion of the action, the redux store calls the reducer where with the current state and the action. Here, the redux state can be updated based on action.type
(the second code snippet above)
This is the most important part: your component needs to have a mapStateToProps
method which passes values from your Redux state as props into your component. So as the state changes, the props get updated and the component re-renders. To use mapStateToProps
, you need to implement connect from the react-redux library. (https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)
To achieve what you want, this is what I suggest:
In your component's componentWillReceiveProps
method, checking for props.isAuthenticated
and using context.router.push()
to navigate if the user is authenticated.
Also having a check based on props.isAuthenticated
in the component's render
method to show the error message.
A few links which could be useful:
https://redux.js.org/basics/data-flow
https://redux.js.org/basics/usage-with-react
I prefer code like this:
const mapStateToProps = (state) => {
return {
isAuthenticated: state.isAuthenticated
}
}
class Dashboard extends PureComponent {
render() {
const { isAuthenticated } = this.props
return (
<div>
{ isAuthenticated ? (
<div>
<p>Hello</p>
</div>
) : (
Login()
)}
</div>
)
}
}
Source: https://stackoverflow.com/a/56899814/3850405
Addition to the answer from @Nupur. componentWillReceiveProps()
is considered unsafe and the method name now is: UNSAFE_componentWillReceiveProps()
https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops
Use componentDidUpdate()
instead if you would like this approach, this method is not called for the initial render.
componentDidUpdate(prevProps) {
if (this.props.isAuthenticated ) {
//perform code here
}
}
https://reactjs.org/docs/react-component.html#componentdidupdate
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With