You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:40:33