I would like to encapsulate the logic for a function to send push notifications so that it can be called from anywhere in the app. The push notifications API requires a jwtToken to be passed in the header. I want to call useContext on the AuthContextProvider to extract the token but the rules of hooks don't allow my function to call useContext since it isn't a React function component.
import React, { useContext } from "react";
import { AuthContext } from "@context/AuthContextProvider";
export const sendPushNotification = async function (notificationObject) {
const { authData } = useContext(AuthContext); //**<-- Fails with hooks error**
const authToken = authData.signInUserSession.idToken.jwtToken;
...
Here is the code that calls the function:
function AddToDoScreen() {
...
function handleSubmitAsync() {
...
let pushNotificationObject = {
profileIDs: [values.profileID],
title: "Push Notification Title",
body: "Push Notification Message",
};
sendPushNotification(pushNotificationObject);
I think this can be accomplished with a custom hook, but I'm not sure how. I tried starting the function name with use, but that didn't help.
Any pointers on how to implement this so I don't have to get the IdToken in each function that wants to call the sendPushNotification function?
BTW, I know you can't call Hooks inside nested functions. I tried moving the code up into the AddToDoScreen function but got the same error.
CodePudding user response:
You've basically two options here:
Create a custom hook that encapsulates all the logic and returns a callback function a component can invoke.
import React, { useCallback, useContext } from "react"; import { AuthContext } from "@context/AuthContextProvider"; export const usePushNotification = () => { const { authData } = useContext(AuthContext); const authToken = authData.signInUserSession.idToken.jwtToken; const sendPushNotification = useCallback(async (notificationObject) => { ... logic to use token and notification object and send push ... }, [authToken]); return { sendPushNotification }; };
function AddToDoScreen() { const { sendPushNotification } = usePushNotification(); ... function handleSubmitAsync() { ... const notification = { profileIDs: [values.profileID], title: "Push Notification Title", body: "Push Notification Message", }; sendPushNotification(notification); } ... }
Access the
authToken
value from the context in the React component and pass it to the callback function.export const sendPushNotification = async ({ authToken, notification, }) => { ... logic to use token and notification object and send push ... };
function AddToDoScreen() { const { authData } = useContext(AuthContext); const authToken = authData.signInUserSession.idToken.jwtToken; ... function handleSubmitAsync() { ... const notification = { profileIDs: [values.profileID], title: "Push Notification Title", body: "Push Notification Message", }; sendPushNotification({ authToken, notification, }); } ... }