收到警告:无法在渲染内的现有状态转换期间更新

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

关于这个警告已经有很多问题,但我不明白为什么我的代码会导致这个警告。只是尝试一个基本的登录屏幕来获取手机号码。如果号码有效,发送 otp 的操作将被发送,用户将被导航到另一个屏幕。 注释掉了几行 setState 行,但仍然收到此警告。任何帮助表示赞赏。 代码:

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>
        )
    }
}

更新: 警告信息如下

  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)

看来你的问题出在你的fn调用上。 虽然我不知道你是在什么时候收到你的登录信息的,但是,你应该做如下的事情。

  1. 从 return 中删除您的函数调用。

问题是每当 React 重新渲染你的组件时,你的函数就会被调用。我可以想象这是一个问题的一种方式是,如果您已经离开组件,那么调用了这个函数,但是这个组件没有从堆栈中删除,所以它会尝试在您的导航事件期间重新呈现. 这不是您问题的确切原因,但它可能是此类警告的触发因素。

  1. 将导航移到 componentDidUpdate 内。

这样你的函数将只被调用一次,当你的道具发生变化时,并且在渲染阶段不会发生导航,因为这个生命周期方法是在你的组件渲染之后调用的。

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>
        )
    }
}