0

I have created a custom function component which has eventlistener from NetInfo for internet connection, which returns a bool value and method name. I wanted to call the method in every class component to check the internet connect and use the bool value to check the connection status.

Below is my code.

//function Component
import React, { PureComponent, useEffect, useState } from 'react';
import  NetInfo  from "@react-native-community/netinfo";


export default () => {
const [isInternetReachable, setIsInternetReachable] = useState(false)
const InternetChecker = () => {
    useEffect(() => {
        // Subscribe
        const unsubscribe = NetInfo.addEventListener((state) => {
            setIsInternetReachable(state.isInternetReachable);
            console.log("Connection type", state.type);
            console.log("Is internet Reachable?", isInternetReachable);
        });
        return () => {
            unsubscribe();
        };
    },[])
}

return [InternetChecker, isInternetReachable];

};

Class Component trying to access InternetChecker() method

class HomeScreen extends React.Component {

 render() {
 const { navigate } = this.props.navigation;
 const [InternetChecker, isInternetReachable] = InternetHanlder();
 // if (!isInternetReachable) {
 //     <NoNetworkSign /> 
 // }
 InternetChecker()
 if (isInternetReachable){
  console.log("Internet is Reachable");
 } else {
  console.log("No Internet Connection");
  
 }
 return (
  <SafeAreaView style={styles.container}>
    <View style={styles.container}>
    </View>
  </SafeAreaView>
 )
 };

When i try to access in the above way, i'm getting invalid hook call, Hooks can only be called from inside the body of a function component. How can we call it from a Class Component.

Any help appreciated.

1
  • That is not a functional component. If anything it is a custom hook (A hook that is composed of other hooks). Components return jsx and are intended to be rendered. Your function doesn't return anything that can be rendered and you also call it as if it was a hook. You can't call hooks in a class component, also you can't call functions that call hooks in a class component. Commented Jul 8, 2020 at 7:54

3 Answers 3

2

Add a name to the function

import React, { PureComponent, useEffect, useState } from 'react';
import  NetInfo  from "@react-native-community/netinfo";


export default ConnectivityChecker = () => {
const [isInternetReachable, setIsInternetReachable] = useState(false)
const InternetChecker = () => {
    useEffect(() => {
        // Subscribe
        const unsubscribe = NetInfo.addEventListener((state) => {
            setIsInternetReachable(state.isInternetReachable);
            console.log("Connection type", state.type);
            console.log("Is internet Reachable?", isInternetReachable);
        });
        return () => {
            unsubscribe();
        };
    },[])
}

return [InternetChecker, isInternetReachable];

};

where you want to use this function you should import it

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

1 Comment

Can you please also mention, how this can be imported in another component? Either in class or functional component.
1

First you should read the Hooks Rules, The first rule is do not call a react hook inside a class based Component, Thus simply update the HomeScreen component as a FC Component then try again it will surly Work.

And your custom hooks should be like this:

 export const useInternetStatus = () => {// I make a name to your hook is best in inspection and testing
const [isInternetReachable, setIsInternetReachable] = useState(false)
const InternetChecker = () => {
    useEffect(() => {
        // Subscribe
        const unsubscribe = NetInfo.addEventListener((state) => {
            setIsInternetReachable(state.isInternetReachable);
            console.log("Connection type", state.type);
            console.log("Is internet Reachable?", isInternetReachable);
        });
        return () => {
            unsubscribe();
        };
    },[isInternetReachable]) // in order to re-call the hooks whenever the netInfo status changed 
}

return [InternetChecker, isInternetReachable];

};

1 Comment

The naming convention for a hook is useXYZ so it should be useInternetStatus in that case. If you name it like this it will also be linted by the react hooks linting rule to warn you from missusing it.
0

The function you have shown is not a functional component as it doesn't return something that can be rendered. Also you are calling it like a hook. What you can do is to first fix the issues with your custom hook:

  1. It returns a hook (a function InternetChecker that calls useEffect). That is not needed. The hook should just call the useEffect itself, so it will subscribe to the NetInfo when mounting.

  2. The unsubscribe function should, as its name already suggests, unsubscribe from the NetInfo. Otherwise it will lead to memory leaks as your listener will be called even when your component already unmounted.

const useInternetStatus = () => {
    const [reachable, setReachable] = useState(false);
    
    useEffect(() => {
        const subscribe = state => setReachable(state.isInternetReachable); 

        NetInfo.addEventListener(subscribe);

        return () => NetInfo.removeEventListener(subscribe);
    },[]);

    return reachable;
};

Then you could re-write your HomeScreen component to be a functional component too which allows you to use the hook inside of it:

const HomeScreen = () => {
    const isInternetReachable = useInternetStatus();

    console.log(isInternetReachable);

    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.container}>
            </View>
        </SafeAreaView>
    );
};

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.