score:19
The main consideration (from a performance standpoint) for what to group together is less about which ones are used together and more about which ones change together. For things that are mostly set into context once (or at least very infrequently), you can probably keep them all together without any issue. But if there are some things mixed in that change much more frequently, it may be worth separating them out.
For instance, I would expect deviceTheme
to be fairly static for a given user and probably used by a large number of components. I would guess that popup
might be managing something about whether you currently have a popup window open, so it probably changes with every action related to opening/closing popups. If popup
and deviceTheme
are bundled in the same context, then every time popup
changes it will cause all the components dependent on deviceTheme
to also re-render. So I would probably have a separate PopupContext
. windowSize
and windowScroll
would likely have similar issues. What exact approach to use gets deeper into opinion-land, but you could have an AppContext
for the infrequently changing pieces and then more specific contexts for things that change more often.
The following CodeSandbox provides a demonstration of the interaction between useState and useContext with context divided a few different ways and some buttons to update the state that is held in context.
You can go to this URL to view the result in a full browser window. I encourage you to first get a handle for how the result works and then look at the code and experiment with it if there are other scenarios you want to understand.
score:0
You can still combine them! If you are concerned about performance, you can create the object earlier. I don't know if the values you use change, if they do not it is quite easy:
state = {
allContextValue: {
setProfile,
profileReload,
deviceTheme,
setDeviceTheme,
clickEvent,
usePopup,
popup,
windowSize
}
}
render() {
return <AllContext.Provider value={this.state.allContextValue}>...</AllContext>;
}
Whenever you then want to update any of the values you need to do I like this, though:
this.setState({
allContextValue: {
...this.state.allContextValue,
usePopup: true,
},
});
This will be both performant, and relatively easy as well :) Splitting those up might speed up a little bit, but I would only do that as soon as you find it is actually slow, and only for parts of your context that would have a lot of consumers.
Still, if your value does not change a lot, there is really nothing to worry about.
score:0
Based on Koushik's answer I made my own typescipt version.
import React from "react"
type TestingContextType = {
value1?: string,
value2?: string,
value3?: string,
value4?: string,
value5?: string,
}
const contextDefaultValues = {
data: {
value1: 'testing1',
value2: 'testing1',
value3: 'testing1',
value4: 'testing1',
value5: 'testing1'
} as TestingContextType,
setData: (state: TestingContextType) => {}
};
const TestingContext = React.createContext(contextDefaultValues);
const TestingComponent = () => {
const {data, setData} = React.useContext(TestingContext);
const {value1} = data
return (
<div>
{value1} is here
<button onClick={() => setData({ value1 : 'newline value' })}>
Change value 1
</button>
</div>
)
}
const App = () => {
const [data, setData] = React.useState(contextDefaultValues.data)
const changeValues = (value : TestingContextType) => setData(data && value);
return (
<TestingContext.Provider value={{data, setData: changeValues}}>
<TestingComponent/>
{/* more components here which want to have access to these values and want to change them*/}
</TestingContext.Provider>
)
}
score:2
The answer by Ryan is fantastic and you should consider that while designing how to structure the context provider hierarchy.
I've come up with a solution which you can use to update multiple values in provider with having many useState
s
Example :
const TestingContext = createContext()
const TestingComponent = () => {
const {data, setData} = useContext(TestingContext)
const {value1} = data
return (
<div>
{value1} is here
<button onClick={() => setData('value1', 'newline value')}>
Change value 1
</button>
</div>
)
}
const App = () => {
const values = {
value1: 'testing1',
value2: 'testing1',
value3: 'testing1',
value4: 'testing1',
value5: 'testing1',
}
const [data, setData] = useState(values)
const changeValues = (property, value) => {
setData({
...data,
[property]: value
})
}
return (
<TestingContext.Provider value={{data, setData: changeValues}}>
<TestingComponent/>
{/* more components here which want to have access to these values and want to change them*/}
</TestingContext.Provider>
)
}
score:5
This answer already does a good job at explaining how the context can be structured to be more efficient. But the final goal is to make context consumers be updated only when needed. It depends on specific case whether it's preferable to have single or multiple contexts.
At this point the problem is common for most global state React implementations, e.g. Redux. And a common solution is to make consumer components update only when needed with React.PureComponent
, React.memo
or shouldComponentUpdate
hook:
const SomeComponent = memo(({ theme }) => <div>{theme}</div>);
...
<AllContext>
{({ deviceTheme }) => <SomeComponent theme={deviceTheme}/>
</AllContext>
SomeComponent
will be re-rendered only on deviceTheme
updates, even if the context or parent component is updated. This may or may not be desirable.
Source: stackoverflow.com
Related Query
- How to use React Hooks Context with multiple values for Providers
- React - Material-UI - How to use Select with multiple values inside react-hook-form
- How to use multiple providers for a single store in react redux
- Context API - multiple providers + React hooks for multiple pages?
- How to use context with hooks for authentication?
- How can I create multiple instances of a React component (having an infinite animation) with different values for the :root variables
- How to type react custom hooks to use with context in TypeScript?
- How to populate values for multiple input field using Material UI Autocomplete and react hooks
- How can I use multiple refs for an array of elements with hooks?
- How to use context api with react router v4?
- how to create React search filter for search multiple object key values
- How do you update Formik initial values with the react context api values after an AJAX request?
- How to use React Context with useState hook to share state from different components?
- Next.js: How can I use getStaticProps/getStaticPaths for sites with multiple domains/hostnames?
- Better aproach for destructing Custom React Hooks with multiple returns?
- How to use a different delay for each item with React transition group?
- How to use React Hooks with video.js?
- How to use static variables with react hooks
- How to use Turborepo for an existing react app created with Create React App in order to make it a monorepo?
- How to use multiple $splice on same collection with React Immutability Helpers
- How to use react context api with getDerivedStateFromProps?
- How to use RichUtils with React Hooks
- Next.js - How do I use Provider to Wrap Routes and use Context with Hooks
- How to use one vendor chunk file (webpack) for multiple react projects
- ReactJS How do I use state hooks for a list of text changing buttons with a timeout?
- How to use react hooks on react-native with react-navigation
- In React, how to use one method to toggle states for multiple checkboxes values
- How to use React Context API to have a state across multiple Routes?
- How to use setTimeout() along with React Hooks useEffect and setState?
- How can I use a React 16.3 Context provider with redux store?
More Query from same tag
- Can you import using absolute paths in React?
- How can I upload image to database with react-image-upload dependency?
- Styled-Components: specify styles of children on parents hover
- Disable floating top left label animation material-ui password input ReactJS
- One of my component in React is not loading while the rest of the components load fine
- Next.js: How to change css of root div __next on specific page?
- ReactJs how to hide load more option after all data fetch from database?
- Find all instances of React component by Tag name
- How to only run function when button is submitted with key "Enter" - React Js
- Webpack adding 'no exports provided' to module with exports
- typescript: Better way to type optional without default value?
- how to use events in react html parser
- How to clear entire react material ui table conent
- How to frame a URL in parent component and pass it to child component using react?
- Why setState doesn't stack like the one before?
- LOOKUP property of MATERIAL-TABLE doesn't change initialValue
- how to pause the Mock Service Worker for testing the intermediate state, in react testing library?
- How to use componentdidmount in modal only when i use modal?
- Passing Props From Parent To Child After Axios and UseEffect Render
- Restyling Bootstrap with Typescript styled component
- React - checkbox not update when multiple unselect
- I'm trying to pack several files into an array, but only one is shown at a time
- How to resolove ReactJS Background Image not working
- Using a Set data structure in React's state
- How can i get a client side cookie with next.js?
- Update state gradually over several seconds
- React Native - Animated Functional Components
- How to connect docker-compose with react and spring boot
- React event handlers not binding properly
- Class is not applied to Material UI button component