I have run into this situation a handful of times using React, but haven’t figured out a nice way to solve it, looking for a standard technique.
Basically, I want to use a React context more than once, in a nested way, but somehow be able to distinguish between the two.
Is it possible to do something like this?
import React, { useContext, useState } from 'react';
function MyApp() {
const [selectedA, setSelectedA] = useState('');
const [selectedB, setSelectedB] = useState('');
return (
<MyCustomContext.Provider
value={{ id: 'a', selected: selectedA, setSelected: setSelectedA }}
>
<MyCustomContext.Provider
value={{ id: 'b', selected: selectedB, setSelected: setSelectedB }}
>
<MyPage />
</MyCustomContext.Provider>
</MyCustomContext.Provider>
);
}
function MyPage() {
const { selected, setSelected } = useContext(MyCustomContext, 'a');
return (
<>
<button onClick={() => setSelected('button')}>Select me</button>
{selected === 'button' && <MyDrawer />}
</>
);
}
function MyDrawer() {
const { selected, setSelected } = useContext(MyCustomContext, 'b');
return (
<div onClick={() => setSelected('this')}>
{selected === 'this' ? 'I am selected' : null}
</div>
);
}
This would mean when the button is selected, the drawer opens. The open drawer then can be selected, to display a message. Meanwhile, the button is still staying selected. So you have two independent selection usages at once.
In reality, these two providers could be instantiated at arbitrary points in the React DOM tree, not necessarily so close together. But they would be nested inside each other, and one set of code might use selection to do one thing, while a different set of code uses selection context to do another thing. They both rely on the same functionality of the context/provider.
This is an overly simplified example, but you can imagine a more complex use case where you have selection managed for a datagrid in one example, and for the surrounding app form/ui or something like that. One is instantiated at the top-level, the other at the datagrid level, but the datagrid one is overriding the global one now. How can that be solved/fixed, without having to just duplicate the context module, creating two instances of the context constructor so useContext(Constructor)
will be happy.