0

I would have liked to know how to navigate from screen to screen from the React Navigation module using the useNavigation() function inside of a component. According to the documentation, you must include the useNavigation() function by including an onPress inside my tag (here ). The problem is that it shows me the following error: 'Invariant violation: Invalid call. Hook can only be called inside of the body of a function component.'

My React Native Component :

import React, { Component } from 'react';
import {View, StyleSheet, Image, TouchableOpacity} from "react-native";
import { Text } from 'react-native-elements';
import { LinearGradient } from 'expo-linear-gradient';
import PropTypes from 'prop-types';
import { useNavigation } from '@react-navigation/native';

export default class HorizontalCard extends Component {
    static propTypes = {
        screen: PropTypes.string,
        title: PropTypes.string,
        desc: PropTypes.string,
        img: PropTypes.string,
      }
    render() {
        const navigation = useNavigation();
        return (
             <TouchableOpacity onPress={() => navigation.navigate(this.props.screen)} style={styles.container}>
                <View style={styles.card_discord}>
                    <Image style={styles.card_discord_img} source={{uri: this.props.img}} />
                        <LinearGradient
                            start={[1.0, 0.5]}
                            end={[0.0, 0.5]}
                            colors={['rgba(42, 159, 255, 0.2)', '#333333', '#333333']}
                            style={styles.FadeAway}>
                            <View style={styles.FadeAway}>
                                <Text h4 style={styles.FadeAway_h2}>{this.props.title}</Text>
                                <Text style={styles.FadeAway_p}>{this.props.desc}</Text>
                            </View>
                        </LinearGradient>
                </View>   
            </TouchableOpacity>
        )
    }
}

Thanks. Regards,

Quentin

3 Answers 3

2

You cannot implement your components as classes if you want to use hooks.

So, if you want to use hooks, you should implement your components as functions since the hooks can only be called inside the body of a function component.

So, your component should be as follows.

Implementing component as s FUNCTION and using HOOKS.

import React from 'react';
import { View, StyleSheet, Image, TouchableOpacity } from 'react-native';
import { Text } from 'react-native-elements';
import { LinearGradient } from 'expo-linear-gradient';
import PropTypes from 'prop-types';
import { useNavigation } from '@react-navigation/native';

export function HorizontalCard(props) {
  const navigation = useNavigation();

  return (
    <TouchableOpacity
      onPress={() => navigation.navigate(props.screen)}
      style={styles.container}>
      <View style={styles.card_discord}>
        <Image style={styles.card_discord_img} source={{ uri: props.img }} />
        <LinearGradient
          start={[1.0, 0.5]}
          end={[0.0, 0.5]}
          colors={['rgba(42, 159, 255, 0.2)', '#333333', '#333333']}
          style={styles.FadeAway}>
          <View style={styles.FadeAway}>
            <Text h4 style={styles.FadeAway_h2}>
              {props.title}
            </Text>
            <Text style={styles.FadeAway_p}>{props.desc}</Text>
          </View>
        </LinearGradient>
      </View>
    </TouchableOpacity>
  );
}

HorizontalCard.propTypes = {
  screen: PropTypes.string,
  title: PropTypes.string,
  desc: PropTypes.string,
  img: PropTypes.string,
};

But, if you still needs to implement your component as a class, you can forget about using useNavigation hook and continue with this.props.navigation instead.

In that case, your component should be as follows.

Implement component as a CLASS and WITHOUT HOOKS

import React, { Component } from 'react';
import { View, StyleSheet, Image, TouchableOpacity } from 'react-native';
import { Text } from 'react-native-elements';
import { LinearGradient } from 'expo-linear-gradient';
import PropTypes from 'prop-types';

export default class HorizontalCard extends Component {
  constructor(props) {
    super(props);
  }

  static propTypes = {
    screen: PropTypes.string,
    title: PropTypes.string,
    desc: PropTypes.string,
    img: PropTypes.string,
  };

  render() {
    return (
      <TouchableOpacity
        onPress={() => this.props.navigation.navigate(this.props.screen)}
        style={styles.container}>
        <View style={styles.card_discord}>
          <Image
            style={styles.card_discord_img}
            source={{ uri: this.props.img }}
          />
          <LinearGradient
            start={[1.0, 0.5]}
            end={[0.0, 0.5]}
            colors={['rgba(42, 159, 255, 0.2)', '#333333', '#333333']}
            style={styles.FadeAway}>
            <View style={styles.FadeAway}>
              <Text h4 style={styles.FadeAway_h2}>
                {this.props.title}
              </Text>
              <Text style={styles.FadeAway_p}>{this.props.desc}</Text>
            </View>
          </LinearGradient>
        </View>
      </TouchableOpacity>
    );
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much for your solution actually I understand better now !
@SennenRandika just suggestion, the class based version can be used with a hook by wrapping inside a functional component, you can check out the docs here reactnavigation.org/docs/use-navigation
@GuruparanGiritharan Yeah... I was not aware of that. I thought we must use function components if we want to use hooks. Thank you for commenting here and letting me know about that. :-)
You are welcome, We do that but for navigation the wrapping workaround can be used :)
1

You can also wrap your class component in a function component to use the hook and get it though props:

class MyBackButton extends React.Component {
  render() {
    // Get it from props
    const { navigation } = this.props;
  }
}

// Wrap and export
export default function(props) {
  const navigation = useNavigation();

  return <MyBackButton {...props} navigation={navigation} />;
}

Comments

0

You cannot use hooks inside Class components, as it clearly says in the error. Please check React documentation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.