React Native封装推送通知函数遇useContext Hooks规则限制问题
解决方案:封装全局可用的推送通知逻辑
核心思路
把纯发送逻辑和React上下文依赖分离:先写一个不依赖React的工具函数处理API请求,再通过自定义Hook获取上下文里的token,返回一个已经绑定token的推送函数,这样组件调用时无需手动传token。
步骤1:编写纯工具函数(无React依赖)
这个函数只负责接收通知内容和token,完成API请求,不涉及任何React Hooks:
// sendPushNotificationCore.js export const sendPushNotificationCore = async (notificationObject, authToken) => { try { const response = await fetch('你的推送API接口地址', { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify(notificationObject) }); if (!response.ok) { throw new Error(`推送失败: ${response.statusText}`); } return await response.json(); } catch (error) { console.error('发送推送通知出错:', error); throw error; // 抛出错误让调用方处理 } };
步骤2:编写自定义Hook(获取token并绑定发送函数)
在自定义Hook的顶层调用useContext(符合Hooks规则),返回一个已经自动携带token的推送函数:
// usePushNotification.js import { useContext, useCallback } from 'react'; import { AuthContext } from '@context/AuthContextProvider'; import { sendPushNotificationCore } from './sendPushNotificationCore'; export const usePushNotification = () => { const { authData } = useContext(AuthContext); // 用useCallback缓存函数,避免组件每次渲染都创建新函数 const sendPushNotification = useCallback(async (notificationObject) => { // 校验token有效性,提前抛出错误 if (!authData?.signInUserSession?.idToken?.jwtToken) { throw new Error('未获取到有效登录凭证,请检查用户登录状态'); } const authToken = authData.signInUserSession.idToken.jwtToken; return await sendPushNotificationCore(notificationObject, authToken); }, [authData]); // 依赖authData,token刷新时自动更新函数 return sendPushNotification; };
步骤3:组件中调用
在任意React函数组件的顶层调用自定义Hook,直接使用返回的推送函数即可:
// AddToDoScreen.js import { usePushNotification } from './usePushNotification'; function AddToDoScreen() { // 在组件顶层调用自定义Hook,获取推送函数 const sendPushNotification = usePushNotification(); async function handleSubmitAsync() { // ...你的表单处理逻辑 const pushNotificationObject = { profileIDs: [values.profileID], title: "Push Notification Title", body: "Push Notification Message", }; try { await sendPushNotification(pushNotificationObject); console.log('推送发送成功'); // 这里可以添加用户提示(如Toast) } catch (error) { console.error('推送失败:', error); // 处理错误逻辑 } } // ...组件其他代码 }
为什么之前改use开头没用?
自定义Hook必须在React函数组件或其他自定义Hook的顶层调用,你之前只是给普通异步函数改了名字,但useContext还是嵌套在异步函数内部,违反了Hooks的调用规则。现在的实现完全符合规则,同时实现了全局复用且无需手动传token的需求。
内容的提问来源于stack exchange,提问作者Dave Fish
相关产品推荐
相关产品推荐

