Better way to use multiple context providers in ReactNative

  1. I'm not sure what you mean with "better". If you just want to clean up your App component, you can abstract the Provider rendering into a separate function. This or this might help you accomplish it according to your needs

  2. If, like your example, you wrap your entire application with all Providers and they are independent of each other, then the order would not matter. Otherwise they behave no different than other components, only children have access to its data and the data flow is unidirectional.

  3. Yes, there is no need to provide all data to your entire application.


Answers

Answer 1:

  1. There is no better way to add app-level provider but some provider do not have context app-level mean (we do not need context in-app everywhere). Some providers have module levels. so you can wrap outside a specific tree or component
const UserScreen = () => (
  <UserProvider>
    <UserScreen />
  <UserProvider />
)

Answer 2:

  1. In working there is no effect but sometimes we need to call the child function from the parent, therefore, we need to use ref. in this nested level provider we have to use forwardRef. Rest of the things work fine.

Answer 3:

  1. Yes we can skip provider in App.js if that provider is not app-level mean we do not need context everywhere in app. if we need context in one or two screens or one tree then we can wrap that screen or tree in provider and do not use in App.js

I won't answer in order it's asked.

Answer 3

If a provider ONLY provides context for a specific Component, you should import and use it in that Component. DO NOT wrap App with it.

The reason is whenever provider is updated, every consumer will be re-render, you can't no use React.memo or ReactPureComponent or shouldComponentUpdate to stop it. You should not overuse context

const Root = () => {
  return (
    <AppProvider>
      <ComponentProvider>
        <App/>
      <ComponentProvider>
    </AppProvider>
  )
}

const App = () => {
  return (
    <>
      <ComponentA/>
      <ComponentB/>
    <>
  )
}

const ComponentContext = createContext()
const ComponentProvider = ({ children }) => {
  // If any value here is updated --> all consumer will be render
  // --> App re-render --> ComponentA and ComponentB re-render
  return (
    <ComponentContext.Provider value={{ value1, value2, value }}>
      {children}
    </ComponentContext.Provider>
  )
}

You should do this instead

const Root = () => {
  <AppProvider>
    <App/>
  </AppProvider>
}

const App = () => {
  return (
   <>
    <ComponentA/>
    <ComponentB/>
   <>
  )
}

const ComponentA = () => {
  return (
    <ComponentProvider>
      <OtherComponent/>
    <ComponentProvider>
   )
}

const ComponentContext = createContext()
const ComponentProvider = ({ children }) => {
  // If any value here is updated --> all consumer (ComponentA only) will be render
  return (
    <ComponentContext.Provider value={{ value1, value2, value3 }}>
      {children}
    </ComponenContext.Provider>
  )
}

Answer 1

Answer 3 can be the answer for this, use context in the right place (For the Components which consume the context only. DO NOT randomly every context at App level). If your context is frequently updated, I recommend not to use other ways so you can use React.memo or PureComponent or shouldComponentUpdate to prevent unwanted re-render to optimise performance.

Answer 2

The order doesn't impact the App.