繁体   English   中英

ReactNative:在现有状态转换期间无法更新(例如在`render`中)。渲染方法应该是道具和状态的纯函数

[英]ReactNative : Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state

这是我的代码,我似乎无法找到问题。 我已经研究过这个问题但是找不到解决方案,所以我转向StackOverflow的神寻求帮助!

如您所见,我想在我的LoadingScreen中加载字体,并在完成后移动到下一个屏幕。 如果有更简单的方法继续让我知道。

import React from 'react';
import { StyleSheet, View, AsyncStorage, Alert, ActivityIndicator } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'
import * as Font from 'expo-font';
import * as firebase from "firebase";


export default class Loading extends React.Component {

constructor(props) {
    super(props);
    this.state = {
        fontLoaded: false,
        client: {
            uid: ""
        }
    };
}


async componentWillMount() {
    //Load fonts + Login to Firebase + capture user ID
    let self = this;
    await Font.loadAsync({
        "Roboto-Regular": require("../assets/fonts/Roboto-Regular.ttf"),
        "Courgette-Regular": require("../assets/fonts/Courgette-Regular.ttf"),
        "Raleway-Regular": require("../assets/fonts/Raleway-Regular.ttf")


    })

    await firebase.auth().signInAnonymously().catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        Alert.alert("Error code : " + errorCode, errorMessage)

    });

    //Register the UID
    await this.setState({ uid: firebase.auth().currentUser.uid })

    this.setState({
        client: {
            ...this.state.client,
            uid: firebase.auth().currentUser.uid
        }
    });




    await this.setState({ fontLoaded: true })



}


render() {

    if (this.state.fontLoaded) {

        return (

            this.props.navigation.navigate("Home", { client: this.state.client })
        )
    }

    return (
        <View style={styles.container}>
            <LinearGradient
                colors={["#5B86E5", "#36D1DC"]}
                style={{ flex: 1 }}
            >
                <View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>

                    <ActivityIndicator size="large" color="#FFF" />

                </View>
            </LinearGradient>
        </View >
    )
}
}

const styles = StyleSheet.create({
    container: {
    flex: 1
}


});

我认为最好加载你的Home屏幕。 执行诸如在页面中获取数据并在操作完成后导航到另一页面之类的操作效率不高。 我认为最好在componentDidMount生命周期中获取数据,并且当收到的数据将fontLoaded更改为true ,如下所示:

import React from 'react';
import { StyleSheet, View, AsyncStorage, Alert, ActivityIndicator } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'
import * as Font from 'expo-font';
import * as firebase from "firebase";


export default class Home extends React.Component {

constructor(props) {
    super(props);
    this.state = {
        fontLoaded: false,
        client: {
            uid: ""
        }
    };
}


async componentDidMount() {
    //Load fonts + Login to Firebase + capture user ID
    let self = this;
    await Font.loadAsync({
        "Roboto-Regular": require("../assets/fonts/Roboto-Regular.ttf"),
        "Courgette-Regular": require("../assets/fonts/Courgette-Regular.ttf"),
        "Raleway-Regular": require("../assets/fonts/Raleway-Regular.ttf")


    })

    await firebase.auth().signInAnonymously().catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        Alert.alert("Error code : " + errorCode, errorMessage)

    });

    //Register the UID
    await this.setState({ uid: firebase.auth().currentUser.uid })

    this.setState({
        client: {
            ...this.state.client,
            uid: firebase.auth().currentUser.uid
        }
    });




    await this.setState({ fontLoaded: true })



}


render() {

    if (this.state.fontLoaded) {

        return (
........... Any code that presents in your Home component

        )
    }

    return (
        <View style={styles.container}>
            <LinearGradient
                colors={["#5B86E5", "#36D1DC"]}
                style={{ flex: 1 }}
            >
                <View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>

                    <ActivityIndicator size="large" color="#FFF" />

                </View>
            </LinearGradient>
        </View >
    )
}
}

const styles = StyleSheet.create({
    container: {
    flex: 1
}


});

我希望它对你有所帮助。 如果这是你想要的解决方案请投票给我:)

您正在混合UI(渲染方法)和函数(在渲染中导航)。 当React检测到状态或道具更新时,该方法将执行多次。

如果这只是一个加载屏幕,那么从渲染中删除条件并只显示一个加载屏幕并从componentDidMount方法导航到下一个屏幕,该方法仅在屏幕加载时触发一次。

这应该删除错误。 基本上,删除setState({fontLoaded:true}),然后从那里导航到下一个屏幕。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM