Creating a DataBag Context that carries around data flexibly in Expo / React Native

When dealing with paramaters that you want available throughout your whole App, you most likely turn to props, Redux or useContext. How to create one bag with data that you can easily access throughout all your app?

First, define your DataBagContext and a custom hook for easy access. Then, define the DataBagProvider component which uses the useState hook to keep track of the state object, and the setValue function to update the state. You can call this ./context/DataBagContext.js:

// ./context/DataBagContext.js
import React, { createContext, useState, useContext } from 'react';

// Create DataBagContext
const DataBagContext = createContext();

// Custom hook for consuming DataBagContext
export const useDataBag = () => useContext(DataBagContext);

export const DataBagProvider = ({ children }) => {
  const [data, setData] = useState({}); // Initially an empty object

  // Function to set or update context data
  const setValue = (key, value) => {
    setData(prevData => ({
      ...prevData,  // Copy all existing data
      [key]: value  // Add new or update existing key
    }));
  };

  // The context value includes the data object and the setValue function
  const contextValue = {
    data,
    setValue
  };

  return (
    <DataBagContext.Provider value={contextValue}>
      {children}
    </DataBagContext.Provider>
  );
};

Ensure the root of your component tree (or any subtree where you need access to the data) is wrapped with DataBagProvider in App.js:

// App.js
import { NavigationContainer } from '@react-navigation/native';
import { DataBagProvider } from './contexts/DataBagContext';

const App = () => {
  return (
    <DataBagProvider>
      <NavigationContainer>
        {/* Your screens and navigation go here */}
      </NavigationContainer>
    </DataBagProvider>
  );
};

export default App;

Consume the context in your components by using the useDataBag hook:

// MyComponent.js
import React from 'react';
import { View, Text, Button } from 'react-native';
import { useDataBag } from './contexts/DataBagContext';

const MyComponent = () => {
  const { data, setValue } = useDataBag();

  // A function to demonstrate setting/updating a value in the context
  const handleUpdateValue = () => {
    setValue('myKey', 'myNewValue');
  };

  return (
    <View>
      {/* Map over the data object and display all variables and values */}
      {Object.entries(data).map(([key, value]) => (
        <Text key={key}>{`${key}: ${value}`}</Text>
      ))}

      <Button title="Update Value" onPress={handleUpdateValue} />
    </View>
  );
};

export default MyComponent;

And from another part of the app, like a component, you can now acces this data. RandomComponent.js

// RandomComponent.js
import React from 'react';
import { View, Text } from 'react-native';
import { useDataBag } from './contexts/DataBagContext';

const RandomComponent = () => {
  const { data } = useDataBag();

  return (
    <View>
      <Text>{data.myKey}</Text>
    </View>
  );
};

export default RandomComponent;

Components that consume useDataBag will have the ability to set and retrieve data from the context dynamically.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top