4
votes

This is my code, I can't seem to find the problem. I've researched the problem but wasn't able to find a solution so I'm turning to the StackOverflow gods for some help !

As you can see I want to load the fonts in my LoadingScreen and move to the next screen once it's done. if there's an easier way to proceed let me know.

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
}


});
2
To add fonts in react native app, there is an ultimate guide to use fonts - Nooruddin Lakhani

2 Answers

3
votes

I think it is better to do load your Home Screen. It is not efficient to do an action like fetching data in a page and navigate to another page after action completion. I think it is better to fetch your data in componentDidMount lifecycle and when data received change your fontLoaded to true as below:

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
}


});

I hope it was helpful for you. If it was your desired solution please vote me up:)

2
votes

You are mixing UI (render method) and functions (navigate inside the render). That method will execute multiple times, when React detects an update in the state or props.

If this is just a loading screen then remove the conditional from the render and just show a loading screen and navigate to the next screen from the componentDidMount method, which will only trigger once when the screen loads up.

That should remove the error. Basically, remove the setState({fontLoaded: true}) and just navigate to the next screen from there.