首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >错误:无效钩子调用。只能在React本机中函数组件的主体内调用钩子

错误:无效钩子调用。只能在React本机中函数组件的主体内调用钩子
EN

Stack Overflow用户
提问于 2021-09-09 16:22:22
回答 2查看 8K关注 0票数 3

我试图在组件中使用useSelector,但是我仍然收到错误,说:Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

backgroundTasks.js:

代码语言:javascript
复制
import axios from "axios";
import AsyncStorage from '@react-native-community/async-storage';
import { baseURL, mlURL } from "../../constants";
import BackgroundFetch from "react-native-background-fetch";
import { useSelector } from "react-redux";
import { showNotification, handleScheduleNotification, handleCancel } from "./notification.android";

const getLatestNotifications = async (headers, user_id) => {
    const Link = `${baseURL}/api/push-notifications`;

    console.log("Push notification Link is", Link);
    try {
        let data = await axios
            .get(
                Link,
                { headers: headers }
            );
        if (data.data.response) {
            console.log("Recieved notification response", data.data.response);
            return data.data.response;
        }
        else {
            return [];
        }
    } catch (err) {
        console.log("Notifications error", err);
        return [];
    }
}

//In startTask I want to use useSeletor but I am getting error.

const startTask = async (task = "notifications") => {
    console.log("Background task started");
    console.log('background');
    const token = await AsyncStorage.getItem("token");
    const user_id = await AsyncStorage.getItem("user_id");
    const userName = await AsyncStorage.getItem("name");
    const notificationsUnReadNumber = useSelector((state) => state.notification.notificationCount); //Here
        console.log(notificationsUnReadNumber);
    const apiHeaders = {
        'x-access-token': token,
        'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0',
        'Accept': 'application/json, text/plain, */*',
    };
    if (task == "notifications" && token) {
        let notifications = await getLatestNotifications(apiHeaders, user_id);
        console.log("Get Latest Notifications data", notifications);
        if (notifications && notifications.length > 0 && notificationsUnReadNumber !==0) {
            console.log('inside notification');
            notifications.forEach((notification) => {
                showNotification(notification.title, notification.content, String(notification._id));
            });
        }

    }

};

const inititalizeBackgroundTasks = async () => {
    const onEvent = async (taskId) => {    //This task will run when app is not terminated (foreground/background)
        console.log('[BackgroundFetch] task: ', taskId);
        // Do your background work...
        console.log("Task background called")
        console.log("Received background-fetch event: ", taskId);
        startTask("notifications");
        BackgroundFetch.finish(taskId);
    }

    // Timeout callback is executed when your Task has exceeded its allowed running-time.
    // You must stop what you're doing immediately BackgorundFetch.finish(taskId)
    const onTimeout = async (taskId) => {
        console.warn('[BackgroundFetch] TIMEOUT task: ', taskId);
        BackgroundFetch.finish(taskId);
    }


    let status = await BackgroundFetch.configure({
        minimumFetchInterval: 15,     //Run Task every 15 minutes
        // Android options
        forceAlarmManager: true,     // <-- Set true to bypass JobScheduler.
        stopOnTerminate: false,
        startOnBoot: true,
        enableHeadless: true,
        requiredNetworkType: BackgroundFetch.NETWORK_TYPE_NONE, // Default
        requiresCharging: false,      // Default
        requiresDeviceIdle: false,    // Default
        requiresBatteryNotLow: false, // Default
        requiresStorageNotLow: false  // Default
    }, onEvent, onTimeout);

    console.log('[BackgroundFetch] configure status: ', status);

};

export { inititalizeBackgroundTasks};

如果我必须使它成为一个组件,那么如何将backgroundTasks导出为default,如何将export {inititalizeBackgroundTasks}导出为常规?

我只想导出一个组件,即inititalizeBackgroundTasks,并在组件中使用其他组件作为函数,所以如果我以错误的方式使用useSelector,我如何使用它?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-09 20:45:53

只从React函数调用钩子

✅从function函数组件调用钩子。

从自定义钩子调用✅钩子

了解更多关于钩子规则的信息,文档中。

我希望这项工作能够帮助您(正如您前面提到的),我们将backgroundTasks导出默认设置为一个功能组件,这样我们就可以使用react。

代码语言:javascript
复制
import { useEffect } from "react";
import axios from "axios";
import AsyncStorage from "@react-native-community/async-storage";
import { baseURL, mlURL } from "../../constants";
import BackgroundFetch from "react-native-background-fetch";
import { useSelector } from "react-redux";
import {
  showNotification,
  handleScheduleNotification,
  handleCancel,
} from "./notification.android";

const getLatestNotifications = async (headers, user_id) => {
  const Link = `${baseURL}/api/push-notifications`;

  console.log("Push notification Link is", Link);
  try {
    let data = await axios.get(Link, { headers: headers });
    if (data.data.response) {
      console.log("Recieved notification response", data.data.response);
      return data.data.response;
    } else {
      return [];
    }
  } catch (err) {
    console.log("Notifications error", err);
    return [];
  }
};

//In startTask I want to use useSeletor but I am getting error.

const startTask = async (task = "notifications", notificationsUnReadNumber) => {
  console.log("Background task started");
  console.log("background");
  const token = await AsyncStorage.getItem("token");
  const user_id = await AsyncStorage.getItem("user_id");
  const userName = await AsyncStorage.getItem("name");
  console.log(notificationsUnReadNumber);
  const apiHeaders = {
    "x-access-token": token,
    "User-Agent":
      "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0",
    Accept: "application/json, text/plain, */*",
  };
  if (task == "notifications" && token) {
    let notifications = await getLatestNotifications(apiHeaders, user_id);
    console.log("Get Latest Notifications data", notifications);
    if (
      notifications &&
      notifications.length > 0 &&
      notificationsUnReadNumber !== 0
    ) {
      console.log("inside notification");
      notifications.forEach((notification) => {
        showNotification(
          notification.title,
          notification.content,
          String(notification._id)
        );
      });
    }
  }
};

export const inititalizeBackgroundTasks = async (notificationsUnReadNumber) => {
  let status = await BackgroundFetch.configure(
    {
      minimumFetchInterval: 15, //Run Task every 15 minutes
      // Android options
      forceAlarmManager: true, // <-- Set true to bypass JobScheduler.
      stopOnTerminate: false,
      startOnBoot: true,
      enableHeadless: true,
      requiredNetworkType: BackgroundFetch.NETWORK_TYPE_NONE, // Default
      requiresCharging: false, // Default
      requiresDeviceIdle: false, // Default
      requiresBatteryNotLow: false, // Default
      requiresStorageNotLow: false, // Default
    },
    async (taskId) => {
      //This task will run when app is not terminated (foreground/background)
      console.log("[BackgroundFetch] task: ", taskId);
      // Do your background work...
      console.log("Task background called");
      console.log("Received background-fetch event: ", taskId);
      startTask("notifications", notificationsUnReadNumber);
      BackgroundFetch.finish(taskId);
    },
    // Timeout callback is executed when your Task has exceeded its allowed running-time.
    // You must stop what you're doing immediately BackgorundFetch.finish(taskId)
    async (taskId) => {
      console.warn("[BackgroundFetch] TIMEOUT task: ", taskId);
      BackgroundFetch.finish(taskId);
    }
  );

  console.log("[BackgroundFetch] configure status: ", status);
};

const backgroundTasks = () => {
  const notificationsUnReadNumber = useSelector(
    (state) => state.notification.notificationCount
  ); //Here

  useEffect(() => {
    if (notificationsUnReadNumber) {
      inititalizeBackgroundTasks(notificationsUnReadNumber);
    }
  }, [notificationsUnReadNumber]);
};

export default backgroundTasks;
票数 3
EN

Stack Overflow用户

发布于 2021-09-09 19:48:12

useSelector导入到调用startTask()的组件中,并将其添加为第二个参数,如startTask('notifications', useSelector)。这应该能解决你的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69121698

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档