I'm new to React (and programming world actually) and I just found that we shouldn't need to use componentWIllReceiveProps / getDerivedStateFromProps at all, but i have this issue:
I have a parent component, LoginForm, in which I fetch my API and use it's response to redirect, if succeed, or to show a Modal if the login fails (LoginFailure component). So then i need to pass from my parent LoginForm to the modal child the loginFailure prop, which changes AFTER the API responses, when my LoginFailureComponent already rendered, so it's like it never knows that the father prop changed. Code Below, sorry it's too long:
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {
username:"",
password:"",
remember:false,
redirect: false,
loginFailure: false
};
this.loginUser = this.loginUser.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
//Here i change the father state according to the API response:
async loginUser() {
await this.props.dispatch(fetchLogin(this.state));
if (this.props.success) { //
this.setState({
redirect: true
})
} else {
this.setState({
loginFailure: true
})
}
}
handleInputChange(event) {
// unimportant code
}
handleForm(e){
//more unimportant code but here i call the api:
this.loginUser()
}
render() {
// WHAT I WILL BE PASSING AS PROPS:
const loginFailure = this.state.loginFailure;
const redirect = this.state.redirect;
if (redirect) {
return <Redirect to={`/profile/${this.props.token}`}/>;
} else {
return ( <div className="text-center">
<h3 className="mb-5">Login</h3>
<Form className="w-100" onSubmit={(e)=>{this.handleForm(e)}}>
{/* Username: */}
//user input code
{/* Password: */}
//password input code
{/* Submit Button: */}
//submit button code
{/*Login Failure component, HERE I PASS THE PROP ACCORDING TO THE STATE VALUE! */}
<LoginFailureModal loginFailure={loginFailure}></LoginFailureModal>
</Form>
</div>
)
}
}
}
This is my child component, now working with willReceiveProps:
class LoginFailureModal extends Component {
constructor(props) {
super(props);
this.state = {
show: false, //i don't initialize with the props
stopShowing: false //and i had to use this second state to STOP re rendering the modal every time i deleted some letter of my wrong input in the father
}
this.handleClose = this.handleClose.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
show: nextProps.loginFailure
})
}
handleClose(){
this.setState({
stopShowing: true
})
};
render() {
if (this.state.stopShowing) {
return null
} else {
return (
<div key={this.props.loginFailure}>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Login Failed!</Modal.Title>
</Modal.Header>
<Modal.Body>
Check your username and password and try again
</Modal.Body>
</Modal>
</div>
)
}
}
}
I read all the React documentation about how we should replace these but i just couldn't apply it to my case, i would be really thankfull if you could guide me with this issue!
Thanks community!
You can use React hooks, and handle your api like this:
// ...
// It's like comoponentDidMount
useEffect({
// Request api
}, [])
// It's like componentWillReceiveProps
// If props.loginFailure was changed, React use this:
useEffect({
// your conditions and ...
}, [props.loginFailure]) // props.loginFailure is a dependency. It's a flag to call inner code