Hey y'all I am trying to use the Context API to manage state to render a badge where the it's not possible to pass props. Currently I am trying to use the setUnreadNotif setter, but it seems because I am using it in a method that loops through an array that it is not working as expected. I have been successful updating the boolean when only calling setUnreadNotif(true/false); alone so I know it works. I have tried many other approaches unsuccessfully and this seems the most straight forward. My provider is wrapping app appropriately as well so I know its not that. Any help is greatly appreciated.
Here is my Context
import React, {
createContext,
Dispatch,
SetStateAction,
useContext,
useState,
} from 'react';
import { getContentCards } from 'ThisProject/src/utils/braze';
import { ContentCard } from 'react-native-appboy-sdk';
export interface NotificationsContextValue {
unreadNotif: boolean;
setUnreadNotif: Dispatch<SetStateAction<boolean>>;
}
export const defaultNotificationsContextValue: NotificationsContextValue = {
unreadNotif: false,
setUnreadNotif: (prevState: SetStateAction<boolean>) => prevState,
};
const NotificationsContext = createContext<NotificationsContextValue>(
defaultNotificationsContextValue,
);
function NotificationsProvider<T>({ children }: React.PropsWithChildren<T>) {
const [unreadNotif, setUnreadNotif] = useState<boolean>(false);
return (
<NotificationsContext.Provider
value={{
unreadNotif,
setUnreadNotif,
}}>
{children}
</NotificationsContext.Provider>
);
}
function useNotifications(): NotificationsContextValue {
const context = useContext(NotificationsContext);
if (context === undefined) {
throw new Error('useUser must be used within NotificationsContext');
}
return context;
}
export { NotificationsContext, NotificationsProvider, useNotifications };
Child Component
export default function NotificationsPage({
navigation,
}: {
navigation: NavigationProp<StackParamList>;
}) {
const [notificationCards, setNotificationCards] = useState<
ExtendedContentCard[]
>([]);
const user = useUser();
const { setUnreadNotif } = useNotifications();
const getCards = (url: string) => {
if (url.includes('thisproject:')) {
Linking.openURL(url);
} else {
navigation.navigate(ScreenIdentifier.NotificationsStack.id, {
screen: ScreenIdentifier.NotificationsWebView.id,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
params: {
uri: `${getTrustedWebAppUrl()}${url}`,
title: 'Profile',
},
});
}
getContentCards((response: ContentCard[]) => {
response.forEach((card) => {
if (card.clicked === false) {
setUnreadNotif(true);
}
});
});
Braze.requestContentCardsRefresh();
};
return (
<ScrollView style={styles.container}>
<View style={styles.contentContainer}>
{notificationCards?.map((item: ExtendedContentCard) => {
return (
<NotificationCard
onPress={getCards}
key={item.id}
id={item.id}
title={item.title}
description={item.cardDescription}
image={item.image}
clicked={item.clicked}
ctaTitle={item.domain}
url={item.url}
/>
);
})}
</View>
</ScrollView>
);
}
Fixed Issue
I was able to fix the issue by foregoing the forEach and using a findIndex instead like so:
getContentCards((response: ContentCard[]) => {
response.findIndex((card) => {
if (card.clicked === false) {
setUnreadNotif(true);
}
setUnreadNotif(false);
});
});