implement
Implement/Control flow/Context

Context is a necessary part of any ui framework. Context allows you to scope state to a specific part of the component tree and create state shared between components without it being global to every instance of that component.

In implement we create context with the context() function.

const MyContext = context<MyContextType>();

Context is then used in 2 stages.

1. Providing the context

You provide the context to child components using the MyContext.Provide() method:

MyContext.Provide(state).To(/* children */);

2. Using the context

Once you need the context wrap your components in MyContext.Use() to get the context:

MyContext.Use((state) => {
	return; /* children */
});

In the example on the right we have a PlantList that has been nested within a PlantListWrapper to create a prop drilling situation.

Let's use what we have learned to refactor this example to make use of Context instead.

We can start by initializing a new context:

const PlantListContext = context<Signal<string[]>>();

Next let's provide that context to our components:

PlantListContext.Provide(vegetables).To(PlantListWrapper());

Finally we need to use that context in our PlantList:

PlantListContext.Use((items) => {
	return Ul(
		ForEach(
			items,
			(_, index) => index,
			(item) => Li(item),
		),
	);
});

Now we can remove all the props fromm PlantListWrapper and PlantList and everything should still work as it did before but without the prop drilling.

index.ts
import { Button, Div, ForEach, H2, Li, signal, Ul, type Signal, context } from "@implementjs/core";

export default function App() {
	const vegetables = signal(["🥕", "🥦", "🥬"]);

	return Div(
		Div({ class: "flex gap-2" }, Button({ onClick: () => vegetables.push("🍅") }, "Add vegetable")),
		PlantListWrapper({ vegetables }),
	);
}

export function PlantListWrapper({ vegetables }: { vegetables: Signal<string[]> }) {
	return Div(
		{ class: "flex gap-6" },
		Div(
			{ class: "flex gap-6" },
			// we can imagine having this list mounted at even deeper levels in the component tree
			Div(H2("Vegetables"), PlantList({ items: vegetables })),
		),
	);
}

export function PlantList({ items }: { items: Signal<string[]> }) {
	return Ul(
		ForEach(
			items,
			(_, index) => index,
			(item) => Li(item),
		),
	);
}
Preview