Recommended patterns for hooking up context providers in React?

Viewed 344

I have a React application, using multiple context providers to pass down data to components, similar to the following (simplified) code.

Here is an example of a context provider, which is consuming the context from another provider:


import React from 'react'
import {useAuth} from './auth-context'

const UserContext = React.createContext()

function UserProvider(props) {
  const {
    data: {user},
  } = useAuth()
  return <UserContext.Provider value={user} {...props} />
}

function useUser() {
  const context = React.useContext(UserContext)
  if (context === undefined) {
    throw new Error(`useUser must be used within a UserProvider`)
  }
  return context
}

export {UserProvider, useUser}

Here are the nested context providers, exported together:


import React from 'react'
import {AuthProvider} from './auth-context'
import {UserProvider} from './user-context'

function AppProviders({children}) {
  return (
    <AuthProvider>
      <UserProvider>{children}</UserProvider>
    </AuthProvider>
  )
}

export default AppProviders

Here are the providers hooked up to the application. <App /> contains all the application components:

import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'
import AppProviders from './context'

ReactDOM.render(
  <AppProviders>
    <App />
  </AppProviders>,
  document.getElementById('root'),
)

Is there a recommended pattern for providing your React application with access to multiple context providers? Is it this?

Secondary question: When context providers are not dependent upon another, does that impact your recommendation? For example, if the UserProvider in the above example did not rely on the AuthProvider and instead looked something like this:


import React from 'react'
import userClient from './userClient'

const UserContext = React.createContext()

function UserProvider(props) {
  const [ user, setUser ] = React.useState(null);
  return (
    <UserContext.Provider value={user} {...props} />
  );
}

function useUser() {
  const context = React.useContext(UserContext)

  if (context === undefined) {
    throw new Error(`useUser must be used within a UserProvider`)
  }
  return context
}

function loadUser() {
  return userClient.loadUser().then(data => {
    setUser(data);
  });
}


export {UserProvider, useUser, loadUser}

In this (second) scenario, are there cons for keeping UserProvider nested inside AuthProvider vs. separating the providers and where they are rendered in the component hierarchy?

0 Answers
Related