Better way to use multiple context providers in ReactNative
Asked Answered
B

4

19

I am having an app in which I am using 3 Context Provider. For the app to work, I have to wrap <App/> in all these providers. As my app grows I am expecting to have a few more providers for more types of data I have to connect with. I have already started to feel that there may be a better way to pass providers into the <App />.

My App.js Code:

import React from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from 'react-navigation';
import { Provider as BlogProvider} from './src/context/BlogContext';
import { Provider as VehicleProvider} from './src/context/VehicleContext';
import { Provider as AuthProvider} from './src/context/AuthContext';

import IndexScreen from './src/screens/IndexScreen';
import ShowScreen from './src/screens/ShowScreen';
import CreateScreen from './src/screens/CreateScreen';
import EditScreen from './src/screens/EditScreen';
import VehicleScreen from './src/screens/VehicleScreen';

const navigator = createStackNavigator(
  {
    Index: IndexScreen,
    Show: ShowScreen,
    Create: CreateScreen,
    Edit: EditScreen,
    Debug: DebugScreen,
    Vehicle: VehicleScreen,

  },
  {
    initialRouteName: 'Index',
    defaultNavigationOptions: {
      title: 'Main'
    }
  }
);

const App = createAppContainer(navigator);

export default () => {
  return (
    <BlogProvider>
      <VehicleProvider>
        <AuthProvider>
             <App />
        </AuthProvider>
      </VehicleProvider>
    </BlogProvider>
  );
};

Some of the questions I have are:

  1. Is there a better way to use multiple context providers in an App.
  2. Does the order in which these providers are nested have any impact on the App?
  3. Can we skip adding provider in <App/> and instead import them in a any screen where it's required and wrap that screen element in it?
Bestride answered 8/3, 2020 at 18:30 Comment(2)
Were you able to get an answer for this? I think im going through the same Stephen Grider course as you did and I had a question on this as wellKeratoid
@alittletf Nop, I just ignored it for the time being. Feel free to post here if you find a way.Bestride
A
14

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.

Alabama answered 30/6, 2020 at 4:0 Comment(0)
A
1

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
Abandoned answered 27/6, 2020 at 10:56 Comment(0)
S
1
  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.

Slavin answered 27/6, 2020 at 10:59 Comment(0)
Z
1
  1. Is there a better way to use multiple context providers in an App.

Answer: Yes

  • you can use whatever number Context Providers to wrap around your App, but make sure that data of those Providers should not be frequently updated and they are treated as global state which means they are accessed or will be accessed from anywhere in your app. Ex: your app theme, authentication status, user's profile,...
  • If data is considered as specific use-case which is only used in just few places in your App, you should not use Context Provider, because if data is updated, all its chilren are forced to re-render, no matters you use any React APIs to prevent it like React.memo. Refer to this
  1. Does the order in which these providers are nested have any impact on the App

Answer: Yes

  • As I said in answer 1, if Provider has data that is updated frequently is parent of those which are having less frequently updates, it will impact all its children, so you can refactor by wrapping the most less updated outermost as parent.
  1. Can we skip adding provider in and instead import them in a any screen where it's required and wrap that screen element in it?

Answer: it is up to your use case.

Zebra answered 2/7, 2020 at 8:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.