You should move all the code from the componentWillMount to the constructor or componentDidMount.
componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead. Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead. This is the only lifecycle hook called on server rendering.
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. This method is a good place to set up any subscriptions. If you do that, don’t forget to unsubscribe in componentWillUnmount(). Calling setState() in this method will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
From the official docs
Answer from Vladimir K. on Stack OverflowYou should move all the code from the componentWillMount to the constructor or componentDidMount.
componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead. Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead. This is the only lifecycle hook called on server rendering.
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. This method is a good place to set up any subscriptions. If you do that, don’t forget to unsubscribe in componentWillUnmount(). Calling setState() in this method will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
From the official docs
componentDidMount isn't deprecated and is definitely still safe to use, so there's no need to add UNSAFE_ to that method. The componentWillSomething methods are the ones that seem to be on their way out. Instead of componentWillMount, use a constructor for the stuff that doesn't produce side-effects, and use componentDidMount for the stuff that does.
componentWillMount is one the first function to be run when creating a component. getDefaultProps is run first, then getInitialState then componentWillMount. Both getDefaultProps and getInitialState will be run only if you create the component with the react.createClass method. If the component is a class extending React.Component, those methods won't be run. It is recommended to use componentDidMount if you can instead of componentWillMount because your component can still be updated before componentWillMount and the first render.
You can find more info on the react component lifecycle here
Also, it is recommended to set the state or the default props inside the class constructor or using getDefaultProps and getInitialState.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { bar: 'foo' };
}
static defaultProps = {
foo: 'bar'
};
}
EDIT: Here's the component handling login
import React, { Component } from 'react';
import { View, Text, ActivityIndicatorIOS } from 'react-native';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from '../../actions';
import LoginButton from '../../components/Login';
import reducers from '../../reducers';
import { Card, CardSection, Button } from '../../components/common';
class Login extends Component {
componentDidMount() {
// If user is already logged in
if(this.props.auth.loggedIn) {
// redirect user here
}
}
componentWillReceiveProps(nextProps) {
// If the user just log in
if(!this.props.auth.loggedIn && nextProps.auth.loggedIn) {
// Redirect user here
}
}
render() {
console.log(this.props.auth);
const { actions, auth } = this.props;
var loginComponent = <LoginButton onLoginPressed={() => actions.login()} />;
if(auth.error) {
console.log("erreur");
loginComponent = <View><LoginButton onLoginPressed={() => actions.login()} /><Text>{auth.error}</Text></View>;
}
if (auth.loading) {
console.log("loading");
loginComponent = <Text> LOL </Text>;
}
return(
<View>
<Card>
<CardSection>
{ auth.loggedIn ? this.props.navigation.navigate('Home') : loginComponent }
</CardSection>
</Card>
</View>
);
}
}
function mapStateToProps(state) {
return {
auth: state.auth
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actionCreators, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
Based on your comment to Ajay's answer, you are looking to set the initial state in the component. To do so, you would set the state inside the constructor function.
class Login extends Component {
constructor(props) {
super(props);
this.state = {
color: props.initialColor
};
}
If you have data that is fetched asynchronously that is to be placed in the component state, you can use componentWillReceiveProps.
componentWillReceiveProps(nextProps) {
if (this.props.auth !== nextProps.auth) {
// Do something if the new auth object does not match the old auth object
this.setState({foo: nextProps.auth.bar});
}
}