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:
<App/>
and instead import them in a any screen where it's required and wrap that screen element in it?We can pass in anything we want to the value prop of the context provider component. So sharing multiple states with one provider is no problem. We create the CountContext with the React.
Consuming Multiple Contexts To keep context re-rendering fast, React needs to make each context consumer a separate node in the tree. If two or more context values are often used together, you might want to consider creating your own render prop component that provides both.
You can use an aspect of es6 destructuring to rename the diff context object properties right inside your component. Like this: const { user, despatch: setUser } = useContext(UserContext); const { theme, despatch: setTheme } = useContext(ThemeContext); const { state, despatch: setState } = useReducer(reducer);
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.
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
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.
Yes, there is no need to provide all data to your entire application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With