收到警告:无法在渲染内的现有状态转换期间更新
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调用上。
虽然我不知道你是在什么时候收到你的登录信息的,但是,你应该做如下的事情。
- 从 return 中删除您的函数调用。
问题是每当 React 重新渲染你的组件时,你的函数就会被调用。我可以想象这是一个问题的一种方式是,如果您已经离开组件,那么调用了这个函数,但是这个组件没有从堆栈中删除,所以它会尝试在您的导航事件期间重新呈现.
这不是您问题的确切原因,但它可能是此类警告的触发因素。
- 将导航移到
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>
)
}
}
关于这个警告已经有很多问题,但我不明白为什么我的代码会导致这个警告。只是尝试一个基本的登录屏幕来获取手机号码。如果号码有效,发送 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调用上。 虽然我不知道你是在什么时候收到你的登录信息的,但是,你应该做如下的事情。
- 从 return 中删除您的函数调用。
问题是每当 React 重新渲染你的组件时,你的函数就会被调用。我可以想象这是一个问题的一种方式是,如果您已经离开组件,那么调用了这个函数,但是这个组件没有从堆栈中删除,所以它会尝试在您的导航事件期间重新呈现. 这不是您问题的确切原因,但它可能是此类警告的触发因素。
- 将导航移到
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>
)
}
}