Skip to content

Instantly share code, notes, and snippets.

@joemaffei
Created March 5, 2024 04:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemaffei/0e31a9480da630efc9030c857905a165 to your computer and use it in GitHub Desktop.
Save joemaffei/0e31a9480da630efc9030c857905a165 to your computer and use it in GitHub Desktop.
Simple dependency injection in React
const $dependencyContext = Symbol();
/**
* The provide function would be called at the root of the application,
* or at the "root" of a dynamically imported module.
*/
function provide<T extends Record<symbol, any>>(deps: T) {
(globalThis as any)[$dependencyContext] = {
...(globalThis as any)[$dependencyContext],
...deps,
};
}
/**
* Simple accessor for the global dependency context.
*/
function inject() {
return (globalThis as any)[$dependencyContext];
}
/** Unique identifier for some dependency. */
const $someDep = Symbol();
/**
* This is decoupled from a specific dependency/import.
*/
const Component = () => {
const { [$someDep]: dep } = inject();
return <div>{dep()}</div>;
};
/**
* This implementation provides Component one version of the dependency.
* In practice, `provide` would not be called multiple times within an
* application for the same dependencies. Imagine this is the "production"
* version of the global App.
*/
const Component1 = () => {
provide({ [$someDep]: () => 'someDep' });
return <Component />;
};
/**
* This implementation provides another version of the dependency.
* Imagine this is the "test" version of the global App.
*/
const Component2 = () => {
provide({ [$someDep]: () => 'someInjectedDep' });
return <Component />;
};
function App() {
return (
<>
<Component1 />
<Component2 />
<Component1 />
<Component2 />
</>
);
}
export default App;
@joemaffei
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment