Better way to use multiple context providers in ReactNative
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 needsIf, 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.Yes, there is no need to provide all data to your entire application.
Answers
Answer 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:
- 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 useforwardRef
. Rest of the things work fine.
Answer 3:
- 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 inApp.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.