Curious_coder
Curious_coder

Reputation: 39

Getting Warning: Cannot update during an existing state transition inside render

There are lots of question around this warning already, but I can't understand why my code is causing this warning. Just trying a basic login screen to get mobile no. and if valid no., action to send otp is dispatched and user is navigated to another screen. Commented out few setState lines but still getting this warning. Any help is appreciated. Code:

class Login extends Component{
state = {
   phone: '',
   validNumber: ''
 }

 handlePhoneChange(value) {
    var regex = /^0[9786]{1}[0-9]{9}/;   
    this.setState({phone: value, validNumber: ''})  
    if(regex.test(value))
    {
      //this.setState({validNumber: 'true'})
       this.props.sendOtp(value)
     }
     else if(value.length == 11) 
    {
      //    this.setState({validNumber: 'false'})
        } 
    }

    onLoginSuccess(){
        const {loginSuccess} = this.props;
        if(loginSuccess != null && loginSuccess != undefined)
        {
            if(loginSuccess === 'YES')
            {
               // this.resetValues()
                this.props.navigation.navigate('Otp')
            }
        }
    }

    resetValues() {
        this.props.resetResponse()
        // this.setState({
        //      phone: '', 
        //     validNumber: ''
        // });
    }

    render(){
        return (
        <View style={{ flex: 1}} >
                <Input 
                placeholder='Enter Mobile Number'
                keyboardType = 'phone-pad' 
                value = {this.state.phone}
                onChangeText = { (value) => { this.handlePhoneChange(value.replace(/\D/g,'')) } }
                inputStyle = {{fontSize: 14}}
                maxLength = {11}
                rightIcon = { this.state.validNumber === 'true'? 
                            <CustomIcon name = 'Tick' size={25} color = 'green'/> : null}
                errorMessage = {this.state.validNumber === 'false'? 'Please enter a valid number' : ''}
                />
                {this.onLoginSuccess()}
        </View>
        )
    }
}

UPDATE: Warning msg is as follows

  ERROR    Warning: Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
    in LoginScreen (created by ConnectFunction)
    in ConnectFunction (created by SceneView)
    in SceneView (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by ForwardRef(CardSheet))
    in ForwardRef(CardSheet) (created by Card)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (created by PanGestureHandler)
    in PanGestureHandler (created by PanGestureHandler)
    in PanGestureHandler (created by Card)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (created by Card)
    in RCTView (at View.js:34)
    in View (created by Card)
    in Card (created by CardContainer)
    in CardContainer (created by CardStack)
    in RCTView (at View.js:34)
    in View (created by MaybeScreen)
    in MaybeScreen (created by CardStack)
    in RCTView (at View.js:34)
    in View (created by MaybeScreenContainer)
    in MaybeScreenContainer (created by CardStack)
    in CardStack (created by Context.Consumer)
    in KeyboardManager (created by Context.Consumer)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:74)
    in SafeAreaProvider (created by Context.Consumer)
    in SafeAreaProviderCompat (created by StackView)
    in RCTView (at View.js:34)
    in View (created by StackView)
    in StackView (created by StackView)
    in StackView
    in Unknown (created by Navigator)
    in Navigator (created by NavigationContainer)
    in NavigationContainer (at App.js:22)
    in Provider (at App.js:21)
    in App (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

Upvotes: 1

Views: 6305

Answers (1)

Konstantin
Konstantin

Reputation: 1458

So it seems that your problem lies in your fn call. Although I don't know at which point you receive your login prop, nevertheless, yo should do something as follows.

  1. Remove your function call from the return.

The problem with that is that whenever React rerenders your component, your function is going to be called. One way this is a problem, that I can imagine, is that if you're already navigating away from the component, so this function was called, but this component was not removed from the stack and so it tries to rerender during your navigation event. This is not the exact reason of your problem, but it's a possible trigger for this kind of warning.

  1. Move your navigation inside componentDidUpdate.

This way your function will be called only once, when your props have changed, and navigation won't happen during the render phase, as this lifecycle method is called after your component renders.

class Login extends Component{
state = {
   phone: '',
   validNumber: ''
 }

 componentDidUpdate(prevProps) {
   if (!prevProps.loginSuccess && this.props.loginSuccess === "YES") {
     this.props.navigation.navigate('Otp')
   }
 }

    render(){
        return (
        <View style={{ flex: 1}} >
                <Input 
                placeholder='Enter Mobile Number'
                keyboardType = 'phone-pad' 
                value = {this.state.phone}
                onChangeText = { (value) => { this.handlePhoneChange(value.replace(/\D/g,'')) } }
                inputStyle = {{fontSize: 14}}
                maxLength = {11}
                rightIcon = { this.state.validNumber === 'true'? 
                            <CustomIcon name = 'Tick' size={25} color = 'green'/> : null}
                errorMessage = {this.state.validNumber === 'false'? 'Please enter a valid number' : ''}
                />
        </View>
        )
    }
}

Upvotes: 2

Related Questions