UseEffect: Invalid hook call. Hooks can only be called inside of the body of a function component

I was trying to get the list of call logs in android using react-native, I wanted to set up a button in which when user clicks permission dialog should've appeared, but instead an error appears as I tried to use useEffect hook as the event fires and hook rules mentions that

Do not call in event handlers

Tried other possibilities but still not able to reach some solutions.

Here is the code snippet I am using:

const ReadLog = ({ navigation }) => {
  const [listData, setListDate] = useState([])

  const ReadFromCalLogs = () => {
    

    useEffect(() => {
      async function fetchData() {
        if (Platform.OS != "ios") {
          try {
            //Ask for runtime permission
            const granted = await PermissionsAndroid.request(
              PermissionsAndroid.PERMISSIONS.READ_CALL_LOG,
              {
                title: "Call Log Example",
                message: "Access your call logs",
                buttonNeutral: "Ask Me Later",
                buttonNegative: "Cancel",
                buttonPositive: "OK",
              }
            )
            if (granted === PermissionsAndroid.RESULTS.GRANTED) {
              CallLogs.loadAll().then((c) => setListDate(c))
              CallLogs.load(3).then((c) => console.log(c))
            } else {
              Alert.alert("Call Log permission denied")
            }
          } catch (e) {
            Alert.alert(e.message)
          }
        } else {
          alert(
            "Sorry! You can’t get call logs in iOS devices because of the security concern"
          )
        }
      }
      fetchData()
    }, [])
  }

  return (
    <View>
    <View style={styles.ReadFromCallLogs}>
      <TouchableOpacity onPress={() => ReadFromCalLogs()}>
        <Text style={{ color: "#009387", marginTop: 15 }}>
          <MaterialCommunityIcons
            size={Dimensions.iconSize}
            name="phone-log-outline"
              >
              </MaterialCommunityIcons>
          Read from Call Logs?
        </Text>
      </TouchableOpacity>
    < /View>
            </View>
  )
}

export default ReadLog


what is the elegant way to do this?


Solution 1:

You can't call a hook inside a function. Hooks can be called only at the top level of the component.

In your code snippet you are calling useEffect() hook inside a normal function ReadFromCalLogs this is what causing the error. However, you don't need to call useEffect() try (Untested):

const ReadFromCalLogs = () => {
  async function fetchData() {
    if (Platform.OS != "ios") {
      try {
        //Ask for runtime permission
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.READ_CALL_LOG,
          {
            title: "Call Log Example",
            message: "Access your call logs",
            buttonNeutral: "Ask Me Later",
            buttonNegative: "Cancel",
            buttonPositive: "OK",
          }
        );
        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
          CallLogs.loadAll().then((c) => setListDate(c));
          CallLogs.load(3).then((c) => console.log(c));
        } else {
          Alert.alert("Call Log permission denied");
        }
      } catch (e) {
        Alert.alert(e.message);
      }
    } else {
      alert(
        "Sorry! You can’t get call logs in iOS devices because of the security concern"
      );
    }
  }
  fetchData().catch((e) => {
    console.warn(e);
  });
};