TAS1987
TAS1987

Reputation: 91

React Native - using hooks with render()

I'm trying to use a font (google fonts) in a react native app. I'm having a problem with the hook:

const [fontsLoaded ,setFontsLoaded] = useState(false);

I believe the problem is around the render() prop. Can anyone advise me on where I should add the above code to get this woking?

My Code is:

import React, { Component, useState } from 'react';
import * as Font from 'expo-font';
import { StyleSheet, Text, View } from 'react-native';
import { AppLoading } from 'expo';

 const getFonts = () => Font.loadAsync({
    'lobster': require('./assets/fonts/Lobster-Regular.ttf')
    });

export default class App extends Component {  
  render() {
    const [fontsLoaded ,setFontsLoaded] = useState(false);
    const gradientHeight=500;
    const gradientBackground  = '#12C1E5';
    const data = Array.from({ length: gradientHeight });

    if(fontsLoaded){
      return (
        <View style={styles.container}>    
          <View style={styles.centering}>
            <Text style={styles.titleText}>Test Title</Text>
          </View> 
          <View style={{flex:1}}>
            {data.map((_, i) => (
              <View
                key={i}
                style={{
                  position: 'absolute',
                  backgroundColor: gradientBackground,
                  height: 1,
                  bottom: (gradientHeight - i),
                  right: 0,
                  left: 0,
                  zIndex: 2,
                  opacity: (1 / gradientHeight) * (i + 2)
                }}
              >
              </View>
            ))}      
          </View>
        </View>
      );
    } else {
      return (
        <AppLoading
          startAsync={getFonts}
          onFinish={() => setFontsLoaded(true)}
        />
      );
    }
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#0e99b5',
    },
  centering: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  titleText: {
    color: 'orange',
    fontSize: 40,
  }
});

The error I'm getting is:

Error: Invalid hook call.

I'm just trying to use the custom font and check that the font is loaded before rendering to the screen.

Upvotes: 0

Views: 731

Answers (1)

Akshay Rao
Akshay Rao

Reputation: 3544

You can't use hooks inside a class component. Hooks are introduced by React to be used in functional components. So you have two options either

  • use setState in your current class component OR
  • convert your class component to functional component.

I'll suggest that you go with functional component as you are not using any life cycles of class component.

If you go with the first approach you can change your code as below:-

export default class App extends Component { 
  state = {
    fontsLoaded: false,
  };

  updateFontsLoadedState = () => {
    this.setState({ fontsLoaded: true });
  }


  render() {
    const { fontsLoaded } = this.state;
    const gradientHeight=500;
    const gradientBackground  = '#12C1E5';
    const data = Array.from({ length: gradientHeight });

    if(fontsLoaded){
      return (
        <View style={styles.container}>    
          <View style={styles.centering}>
            <Text style={styles.titleText}>Test Title</Text>
          </View> 
          <View style={{flex:1}}>
            {data.map((_, i) => (
              <View
                key={i}
                style={{
                  position: 'absolute',
                  backgroundColor: gradientBackground,
                  height: 1,
                  bottom: (gradientHeight - i),
                  right: 0,
                  left: 0,
                  zIndex: 2,
                  opacity: (1 / gradientHeight) * (i + 2)
                }}
              >
              </View>
            ))}      
          </View>
        </View>
      );
    } else {
      return (
        <AppLoading
          startAsync={getFonts}
          onFinish={this.updateFontsLoadedState}
        />
      );
    }
  }
}

If you want to use better approach, use hooks and convert this to functional component then you can do that as below:-

export default function App(props) {
    const [fontsLoaded ,setFontsLoaded] = useState(false);
    const gradientHeight=500;
    const gradientBackground  = '#12C1E5';
    const data = Array.from({ length: gradientHeight });

    if(fontsLoaded){
      return (
        <View style={styles.container}>    
          <View style={styles.centering}>
            <Text style={styles.titleText}>Test Title</Text>
          </View> 
          <View style={{flex:1}}>
            {data.map((_, i) => (
              <View
                key={i}
                style={{
                  position: 'absolute',
                  backgroundColor: gradientBackground,
                  height: 1,
                  bottom: (gradientHeight - i),
                  right: 0,
                  left: 0,
                  zIndex: 2,
                  opacity: (1 / gradientHeight) * (i + 2)
                }}
              >
              </View>
            ))}      
          </View>
        </View>
      );
    } else {
      return (
        <AppLoading
          startAsync={getFonts}
          onFinish={() => setFontsLoaded(true)}
        />
      );
    }
}

Upvotes: 1

Related Questions