'(react native chat) Is there any way to use the global variable independently?

Screenshot

In the banner above the chat, there are two buttons that temporarily turn off the banner and always turn it off. When the user presses the always off button, I hope it applies only to the chat room, but maybe because it is a global variable, it affects other chat rooms. Is there a way to use the global variable independently for each chat?

I thought about making it a key value object and using the id value of the chatroom as the key value, but there is no way to get the id value because I have to allocate it as a global variable.

// ChatScreen
...

<InfoBanner postId={postId} errandInfo={errandInfo} />

    <View style={styles.contents}>
        <GiftedChat 
            messages={messages}
            ...
// InfoBanner
let alwaysOption = true

export default InfoBanner = (props) => {
    const { postId, errandInfo } = props;

    const [bannerVisible, setBannerVisible] = useState(true)

    return (
        <Banner
            visible={alwaysOption && bannerVisible}
            style={styles.banner}
            actions={[
                {
                    label: 'turn off',
                    color: 'black',
                    onPress: () => setBannerVisible(false),
                },
                {
                    label: 'always turn off',
                    color: 'black',
                    style: {justifyContent: 'center'},
                    onPress: () => {alwaysOption=false; setBannerVisible(false)},
                },
            ]}
        >   
        ...



Solution 1:[1]

We could create a custom "hook" that implements a global application cache. We can decide later whether we want to store the chats that should show a banner or not, along with the user ID, on a server or in the phone's local storage.

I will implement a solution using the phone's local storage. It might be useful to store this information in a global cache once it is loaded. I will use Vercel's SWR and react-native-async-storage.

The hook: useChatBanner

import AsyncStorage from '@react-native-async-storage/async-storage';
import useSWR from 'swr'

const keyTemplate = `chat/banner/`

const useChatBanner = (postId) => {
   const {data, error, mutate} = useSWR(postId ? `${keyTemplate}${postId}` : null, () => {
       const value = await AsyncStorage.getItem(`${keyTemplate}${postId}`).then(response => response === "true" ? true : false)
       return value
   })

   const setBannerVisible = React.useCallback((id, visible) => {
       const newData = visible ? "true" : "false"
       mutate(newData, false)
       AsyncStorage.set(`${keyTemplate}${postId}`, new).then(() => {
           mutate(newData)
       })
  }, [data, mutate])
   
   return {
       isVisible: data,
       isLoading: !error && !data,
       isError: error,
       setBannerVisible
   }
}

We need to an additional config wrapper component around our main application for SWR.

import { SWRConfig } from "swr"
export default const App = () => {
    return <SWRConfig>
        // main entry point, navigator code or whatever
    </SWRConfig>
}

Then you can use it as follows in your InfoBanner component.

export default InfoBanner = (props) => {
    const { postId, errandInfo } = props;
    const [bannerVisible, setBannerVisible] = useState(true)
    
    const { isLoading, isVisible } = useChatBanner(postId)


    if (isLoading) {
      // might be useful to show some loading indicator here
      return null
    }

    return (
        <Banner
            visible={isVisible && bannerVisible}
            
           ...

I have included a setter function in the hook in case you want to allow the user to enable the global flag again.

Using the above, it is possible to hold a boolean flag (or any other data) globally for each postId. Notice that we can implement a similar behavior using the Context API.

If you have a server and an user management, then it is very simple to adapt the above code. Replace the async storage calls with your API and you are good to go. If we manage this using userId's rather then postIds, then the data would be an array and we can filter for postIds to retrieve the correct boolean value.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Scholz