React Native普通函数调用useSelector报无效Hook错误如何解决
你的报错本质是违反了React Hook的调用规则:Hook只能在函数组件/自定义Hook的顶层作用域调用,
startTask是普通异步函数,运行在后台任务回调上下文,不属于React组件渲染周期,因此无法调用useSelector。
问题1:改为组件同时支持默认导出、具名导出的实现
如果你确实要把该文件改为React组件,可以按如下方式改造,默认导出组件,同时保留inititalizeBackgroundTasks的具名导出:
// 新增React导入,保留原有其他导入 import React, { useEffect } from 'react'; import { useSelector } from "react-redux"; // 其他原有导入保持不变 // getLatestNotifications 函数原有逻辑不变 const getLatestNotifications = async (headers, user_id) => { // 原有代码不变 } // 改造startTask,接收notificationCount作为入参 const startTask = async (task = "notifications", notificationsUnReadNumber) => { // 删掉原有的useSelector调用,直接用传入的参数 // 其他原有逻辑保持不变 } // 改造inititalizeBackgroundTasks,接收notificationCount参数 const inititalizeBackgroundTasks = async (notificationsUnReadNumber) => { const onEvent = async (taskId) => { console.log('[BackgroundFetch] task: ', taskId); // 执行startTask时传入最新的notificationCount startTask("notifications", notificationsUnReadNumber); BackgroundFetch.finish(taskId); } // 其他原有配置逻辑保持不变 }; // 默认导出的组件 const BackgroundTasks = () => { // 在组件顶层调用useSelector拿状态 const notificationsUnReadNumber = useSelector((state) => state.notification.notificationCount); useEffect(() => { // 组件挂载/状态更新时初始化/刷新后台任务参数 inititalizeBackgroundTasks(notificationsUnReadNumber); }, [notificationsUnReadNumber]) // 该组件不需要渲染任何内容 return null; } export default BackgroundTasks; export { inititalizeBackgroundTasks };
注意:该方案的缺陷是后台任务里拿到的notificationsUnReadNumber是组件触发回调时的快照,如果你需要每次后台任务执行时都拿到最新的状态,推荐用问题2的方案。
问题2:仅导出inititalizeBackgroundTasks的最优解决方案
你这种非组件场景调用Redux状态,不需要用到Hook,直接访问Redux的Store实例调用getState()方法即可,这是最符合你需求的改造方式:
- 首先移除
import { useSelector } from "react-redux"这行,改为导入你项目中创建的Redux Store实例,示例:
// 替换为你项目中实际导出store的路径 import store from '../../store';
- 修改
startTask里获取状态的代码即可,其他所有逻辑不需要改动:
// 原来的useSelector调用替换为这行 const notificationsUnReadNumber = store.getState().notification.notificationCount;
store.getState()可以直接返回当前最新的全局Redux状态,不需要依赖React组件上下文,完美适配后台任务这类非组件场景的调用。
内容的提问来源于stack exchange,提问作者Harsh Mishra
相关产品推荐
相关产品推荐

