【问题标题】:React-Native: Invariant Violation: Maximum update depth exceededReact-Native:不变违规:超过最大更新深度
【发布时间】:2019-12-03 21:31:24
【问题描述】:

我有以下登录屏幕,在将react-native 更新为0.60.4 之前工作正常。

interface OwnProps {
    navigation: any
}

interface StateProps {
    isLoggedIn: boolean,
    isAuthenticating: boolean
}

interface DispatchProps {
    actions: {
        auth: {
            authenticate: (username: string, password: string) => Promise<void>
        }
    }
}

type Props = OwnProps & StateProps & DispatchProps
interface State {
    username: string,
    password: string,
    error?: string,
    fadeAnim: Animated.Value
}

class LoginScreen extends Component<Props, State> {
    static propTypes = {
        isLoggedIn: PropTypes.bool.isRequired,
        isAuthenticating: PropTypes.bool.isRequired,
        actions: PropTypes.shape({
            auth: PropTypes.object
        })
    }

    state: State = {
        username: '',
        password: '',
        error: null,
        fadeAnim: new Animated.Value(1)
    }

    keyboardDidShowListener: EmitterSubscription
    keyboardDidHideListener: EmitterSubscription

    constructor(props) {
        super(props)

        this._onLogin = this._onLogin.bind(this)
        this._handleUsernameChange = this._handleUsernameChange.bind(this)
        this._handlePasswordChange = this._handlePasswordChange.bind(this)
    }

    componentDidMount() {
        this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow)
        this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide)
    }

    componentWillUnmount(): void {
        this.setState({
            username: '',
            password: null,
            error: null,
            fadeAnim: new Animated.Value(1)
        })

        this.keyboardDidShowListener.remove()
        this.keyboardDidHideListener.remove()
    }

    _keyboardDidShow = (): void => {
        Animated.timing(
            this.state.fadeAnim,
            {
                toValue: 0,
                duration: 500
            }
        ).start()
    }

    _keyboardDidHide = (): void => {
        Animated.timing(
            this.state.fadeAnim,
            {
                toValue: 1,
                duration: 500
            }
        ).start()
    }

    _onLogin = (): void => {
        dismissKeyboard()

        if (this.isFormValid()) {
            this.props.actions.auth.authenticate(this.state.username, this.state.password)
                .catch((error: Error) => {
                    const message: string = error ? error.message : 'Si e\' verificato un errore.'
                    this.setState({ error: message })
                    Toast.error(error.message)
                })
        }
    }

    isFormValid(): boolean {
        this.setState({ error: null })

        if (!this.state.username || this.state.username === '') {
            this.setState({ error: 'Username non valido.' })
            Toast.error('Username non valido.')
            return false
        }

        if (!this.state.password || this.state.password === '') {
            this.setState({ error: 'Password non valida.' })
            Toast.error('Password non valida.')
            return false
        }

        return true
    }

    _handleUsernameChange = (username: string) => {
        this.setState({ username })
    }

    _handlePasswordChange = (password: string) => {
        this.setState({ password })
    }

    render(): JSX.Element {
        const { fadeAnim } = this.state

        return (
            <Content
                padder
                style={styles.content}
                contentContainerStyle={styles.contentContainer}
                keyboardShouldPersistTaps='always'
                keyboardDismissMode='on-drag'
            >
                <TouchableWithoutFeedback onPress={dismissKeyboard}>
                    <View style={styles.contentContainer}>
                        <Spinner visible={this.props.isAuthenticating} textContent={'Accesso in corso...'} textStyle={{color: 'white'}} />

                        <Animated.View style={[styles.logosContainer, { opacity: fadeAnim }]}>
                            <Image
                                style={styles.logo}
                                source={require('../../assets/logo.png')}
                            />
                        </Animated.View>

                        <Form style={styles.form}>
                            <Item floatingLabel error={this.state.error ? true : false}>
                                <Label>Username</Label>
                                <Input
                                    autoCapitalize='none'
                                    autoCorrect={false}
                                    value={this.state.username}
                                    onChangeText={this._handleUsernameChange}
                                />
                            </Item>
                            <Item floatingLabel error={this.state.error ? true : false}>
                                <Label>Password</Label>
                                <Input
                                    autoCapitalize='none'
                                    autoCorrect={false}
                                    secureTextEntry
                                    value={this.state.password}
                                    onChangeText={this._handlePasswordChange}
                                />
                            </Item>
                        </Form>

                        {/*this.state.error ? (<FormMessage message={this.state.error} />) : null*/}

                        <Button block success style={styles.loginButton} onPress={this._onLogin}>
                            <Text>Accedi</Text>
                        </Button>
                    </View>
                </TouchableWithoutFeedback>
            </Content>
        )
    }
}

[...]

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen)

更新后,当我尝试输入用户名或密码时,抛出以下期望:

不变违规:超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 React 限制了嵌套更新的数量以防止无限循环。

我在这里阅读了很多关于堆栈溢出和互联网的问题,但似乎没有任何问题可以解决问题。

谁能帮帮我?

【问题讨论】:

    标签: loops react-native input setstate native-base


    【解决方案1】:

    componentWillUnmount() 在组件被卸载和销毁之前立即调用。在此方法中执行任何必要的清理,例如使计时器无效、取消网络请求或清理在 componentDidMount() 中创建的任何订阅。

    您不应该在componentWillUnmount() 中调用setState(),因为该组件永远不会被重新渲染。一旦组件实例被卸载,它将永远不会被再次装载。

    您可以删除componentWillUnmount()中的setState()

        componentWillUnmount(): void {
    
            this.keyboardDidShowListener.remove()
            this.keyboardDidHideListener.remove()
        }
    

    【讨论】:

    • 感谢您的回复,但这并不能解决问题:(
    【解决方案2】:

    不知道为什么,但升级到最新的react-navigation 版本后一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      • 2019-08-29
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 2019-07-06
      • 2018-10-30
      相关资源
      最近更新 更多