React Native - React Navigation Cannot use Hooks in DrawerContent

Viewed 509

I am developing an e-commerce application using React Native and I am trying to use useState in the drawerContent and it tells me this

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

Thank you in advance for your answers.

Here's the code

import React, { useState } from 'react'
import { View, Text, TouchableOpacity, FlatList, StyleSheet, StatusBar } from 'react-native'
import IonIcons from "react-native-vector-icons/Ionicons"
import { categories } from '../../../services/DataTest'
import DrawerSearch from './DrawerSearch'
import DrawerItem from './DrawerItem'

export default function DrawerContent (props) {
    const [search, setSearch] = useState("");

    return (
        <View>
            <TouchableOpacity
                style={styles.customDrawerTouch}
            >
                <View style={styles.backButtonRow}>
                    <IonIcons
                        name="ios-arrow-back"
                        size={25}
                        style={styles.customDrawerIcon}
                        color="#666666"
                    />
                    <Text style={{ color: '#666666' }}>Back to Components</Text>
                </View>
            </TouchableOpacity>
            <DrawerSearch value={search} setValue={setSearch}/>
            <FlatList
                data={categories}
                keyExtractor={(item, index) => index.toString()}
                renderItem={DrawerItem}
            />
        </View>
    );
}

const styles = StyleSheet.create({
    customDrawerTouch: {
        marginTop: StatusBar.currentHeight,
        paddingLeft: 13,
        paddingTop: 15,
    },
    customDrawerIcon: {
        paddingRight: 10
    },
    backButtonRow: {
        flexDirection: 'row',
        alignItems: 'center',
        paddingBottom: 17,
        paddingLeft: 3,
        borderBottomColor: '#F0F0F0',
        borderBottomWidth: 1,
    },
});

I'm using this component here

import * as React from 'react';
import { View, StyleSheet, StatusBar } from 'react-native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import HeaderCategorie from '../../components/categories/index/HeaderCategorie';
import SearchBar from '../../components/home/index/SearchBar';
import DrawerContent from '../../components/categories/index/DrawerContent';

const Drawer = createDrawerNavigator();

function CategoriesScreen({ navigation }) {

    return (
        <View style={styles.container}>
            <HeaderCategorie navigation={navigation}/>
            <View style={styles.headerSearch}>
                <SearchBar />
            </View>
            
        </View>
    )
}

export default function Categories() {
    return (
        <Drawer.Navigator initialRouteName="Categories"
            drawerContent={DrawerContent}
            screenOptions={{headerShown:false}}
        >
            <Drawer.Screen name="Categories" component={CategoriesScreen} />
        </Drawer.Navigator>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: "flex-start",
        alignItems: "center",
        marginTop: StatusBar.currentHeight,
    },
    headerSearch: {
        marginVertical:10
    },
    headerSearchText: {
        fontWeight:"bold",
        fontSize:35,
        marginLeft:20,
        marginVertical:15,
    }
});
1 Answers

Reason: By using drawerContent={DrawerContent}, you are actually passing the reference of the DrawerContent function, which ends up breaking rules of hooks.

So to resolve this, change the following line:

     <Drawer.Navigator initialRouteName="Categories"
            drawerContent={DrawerContent}
            screenOptions={{headerShown:false}}
        >

to this

     <Drawer.Navigator initialRouteName="Categories"
            drawerContent={(props)=> <DrawerContent {...props}/>} // here
            screenOptions={{headerShown:false}}
        >

demo snack

Related