4

In react there's an easy way to share "information" within several layers of components. This is by using context

import {UserCtx} from "./stores/UserCtx"; 
<UserCtx.Provider value={new user(info)}>
    <SomeComponent />
</UserCtx.Provider/>

And then in some component:

import {UserCtx} from "./stores/UserCtx";
function SomeComponent() {
    const userData = React.useContext(UserCtx);
    return <div>JSON.stringify(userData)</div>
}

However this requires the context object definition to be visible for all objects. And thus when creating a library of components it cannot really be used?

Say in above "example" SomeComponent would be a library component, how would I share the context of the main application to the component? Sharing by adding an attribute seems far fetched, at that point I might as well just provide the user (or whatever the context stores) directly?

paul23
  • 8,799
  • 12
  • 66
  • 149
  • There are all sorts of libraries that require you to use their context providers to render their components, so what is your question? I'm not sure it's clear what you're actually asking here... – Jared Smith Sep 21 '20 at 13:58
  • @JaredSmith say I have a set of components, build internally as private library to interoperate with the main application.. This would mean I have to repeat the "logic" of providing the context to all those components. – paul23 Sep 21 '20 at 14:36
  • Again, I don't get it. You create a context provider that has the data you want, you put it near the root of the component tree, and you consume it in your components, just like in the example you posted. There's no repeated logic anywhere, unless you count calls to `useContext` as repeated logic. I think it'd be a little cleaner if you wrapped the context use in a custom hook, but it isn't strictly necessary and I don't understand what is undesirable or not working in the code you posted. – Jared Smith Sep 21 '20 at 14:46
  • 1
    The code is *not working* when `SomeComponent` isn't part of the original project, but instead loaded as a separate package. That package wouldn't have access to `./stores/UserCtx` inside the main project source tree (since it lives in node modules). – paul23 Sep 21 '20 at 14:49
  • So make the context provider part of your custom component library and parameterize its creation with the relevant application state. The caller (main project) will be responsible for instantiating it with the correct data and placing in the render tree, and the consumer (custom library components) consume it. – Jared Smith Sep 21 '20 at 14:51
  • For example, the material-ui datepicker component works this way. It requires you to use their context provider with a date utility library, see https://material-ui-pickers.dev/getting-started/installation – Jared Smith Sep 21 '20 at 14:56
  • @JaredSmith that would work for component `A` but now component `B` also likes to work with this context. (Actually in the concept design the contices are the main shared part between different packages; with the root package just instantiating the context and the root component - and a router). – paul23 Sep 21 '20 at 14:56
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/221821/discussion-between-jared-smith-and-paul23). – Jared Smith Sep 21 '20 at 14:57
  • @paul23 Did you ever get this resolved? I'm running into the same issue and have no idea how to get this working. (I don't have access to the chat, that's linked in Jared Smith's last comment. – Creature Jul 21 '22 at 02:33

2 Answers2

0

All your library of components should be children of the component where value is generated. That is, if your component is the main component exposed to the DOM, value should come there at that top so that any of the components can consume the context.

Mind you, context is wonderful to help you avoid drilling of your components. If you need more flexibility than this, Redux may give you more power.

Niyi Aromokeye
  • 411
  • 5
  • 9
-1

Let's say we have 3 things:

  1. the main project which include the module where the context provider is, and the module where the component library is
  2. the context provider module
  3. the component library project

To make the main project and the component library project share the same context provider, you have not to add the context provider module as a dependency into you component library project but as a dev dependency

  • That's not what dev dependencies are for. https://nodejs.dev/learn/npm-dependencies-and-devdependencies – n.sh Feb 16 '22 at 09:37