The number of components in the array listOfComponents
should be dynamic. In my application components get added and removed over time while the application is running. When I add a new component, I want to add a state for it inside the listOfComponents
array in my ExampleContext
. When I remove a component I want to remove the state. The component should only rerender if the settings in the listOfComponents
get updated where the ids match. How would I go about implementing this?
import React, { createContext, useState } from 'react'
export const ExampleContext = createContext()
export const { Consumer: ExampleConsumer } = ExampleContext
export function ExampleProvider({ children }) {
const [state, setState] = useState({
listOfComponents: [{
id: 1,
settings: {color: 'red'}
},
{
id: 2,
settings: {color: 'blue'}
},
{
id: 3,
settings: {color: 'green'}
}]
})
return (
<ExampleContext.Provider value={[state, setState]}>
{children}
</ExampleContext.Provider>
)
}
export function Component({id}) {
const [state, setState] = useContext(ExampleContext)
return (
<h1> Only rerender me if settings of matching id are updated! </h1>
)
}
Here is how I made it work with useMemo
. Maybe it is helpful for somebody else since it took me some time to figure it out. Also this blog post was pretty helpful. If there is any better way please let me know.
-- App.js
import React, {useContext, useMemo} from 'react';
import {ExampleContext, ExampleProvider} from './Context'
export function Component({id}){
const [state, setState] = useContext(ExampleContext)
function onClick(){
setState(prev => {
return {...prev, [id]: { color: 'blue'}}
})
}
return useMemo(() => {
console.log(`update ${id}`)
return (
<>
<h1 style={{color: state[id].color}}>{id}</h1>
<button onClick={onClick}>{`Update from ${id}`}</button>
</>
)
}, [state[id]])
}
function App() {
return (
<ExampleProvider>
<Component id={1}/>
<Component id={2}/>
</ExampleProvider>
);
}
export default App;
-- Context.js
import React, { createContext, useState } from 'react'
export const ExampleContext = createContext()
export const { Consumer: ExampleConsumer } = ExampleContext
export function ExampleProvider({ children }) {
const [state, setState] = useState({
'1': {color: 'red'},
'2': {color: 'green'},
})
return (
<ExampleContext.Provider value={[state, setState]}>
{children}
</ExampleContext.Provider>
)
}