5

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,
    }
});
2
  • as what it says, you might have some dependency version issue. Delete node_modules and do npm install again. Commented Sep 18, 2021 at 17:41
  • I just tried that and still the same error Commented Sep 18, 2021 at 17:49

1 Answer 1

6

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

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your help, I understood my mistake :)
but i thought DrawerContent is a function component which hasn't been invoked yet. How's the change would make it work?
@windmaomao I had a look at the issues in the react-navigation repo and found this. From my understanding, It seems like the reason is that drawerContent has to be a render function, not an actual function component. But I can't find any official documentation that differentiates the two.
@Moistbobo, thanks i missed that part (props), so it's a render function. Man, maybe this is how router uses as well. Makes sense, thank you very much!!

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.