React Context Module Functions Pattern

The React Context module functions pattern is a design pattern used in React applications to provide and consume data across multiple components without the need for prop drilling.

The pattern involves creating a context using the createContext function from the react package. This context object has two important components: a Provider and a Consumer.

The Provider component is responsible for wrapping the components that need access to the shared data. It accepts a value prop that represents the data that will be shared. The Provider component is typically placed higher up in the component tree to ensure that all nested components can access the shared data.

The Consumer component is used within the components that need access to the shared data. It uses a render prop or a function as a child to access the shared data through a callback function. The Consumer component automatically subscribes to updates from the Provider and re-renders whenever the shared data changes.

To simplify the usage of the Context pattern and encapsulate the logic, it's common to create a separate module that exports functions for interacting with the context.

Here's an example of the React Context module functions pattern:

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

const DataContext = createContext();

export const DataProvider = ({ children }) => {
  const [data, setData] = useState(initialData);

  const updateData = (newData) => {
    setData(newData);
  };

  return (
    <DataContext.Provider value={{ data, updateData }}>
      {children}
    </DataContext.Provider>
  );
};

export const useData = () => useContext(DataContext);

In this example, we define a DataProvider component that wraps its children with the DataContext.Provider. It provides the data state and the updateData function as the value of the context.

The useData custom hook is created to simplify accessing the shared data within components. It uses the useContext hook to retrieve the current context value from the nearest DataProvider ancestor.

Usage example in a component:

import React from 'react';
import { useData } from './DataContext';

const MyComponent = () => {
  const { data, updateData } = useData();

  const handleClick = () => {
    updateData('New data');
  };

  return (
    <div>
      <p>Data: {data}</p>
      <button onClick={handleClick}>Update Data</button>
    </div>
  );
};

export default MyComponent;

In this example, MyComponent uses the useData hook to access the shared data and updateData function from the context. The handleClick function demonstrates updating the shared data using the updateData function.

This pattern allows for a clean and efficient way to share and update data throughout a React application.