UNPKG

rvx

Version:

A signal based rendering library

187 lines (143 loc) 3.69 kB
# Context Contexts can be used to implicitly pass values along the call stack and other rvx APIs. === "JSX" ```jsx import { Context } from "rvx"; // Create a context: const MESSAGE = new Context<string | undefined>(); // Inject a value for the context while running a function: MESSAGE.inject("Hello World!", () => { // Access the current value: MESSAGE.current; // "Hello World!" }); ``` === "No Build" ```jsx import { Context } from "./rvx.js"; // Create a context: const MESSAGE = new Context(); // Inject a value for the context while running a function: MESSAGE.inject("Hello World!", () => { // Access the current value: MESSAGE.current; // "Hello World!" }); ``` You can also inject values for multiple contexts at once: === "JSX" ```jsx import { Context } from "rvx"; const MESSAGE = new Context<string | undefined>(); Context.inject([ MESSAGE.with("Hello World!"), OTHER_CONTEXT.with(...), ... ], () => { MESSAGE.current; // "Hello World!" }); ``` === "No Build" ```jsx import { Context } from "./rvx.js"; const MESSAGE = new Context(); Context.inject([ MESSAGE.with("Hello World!"), OTHER_CONTEXT.with(...), ... ], () => { MESSAGE.current; // "Hello World!" }); ``` ## Default Values Contexts have a global default value which is returned if nothing, `null` or `undefined` is injected. === "JSX" ```jsx import { Context } from "rvx"; const CONTEXT = new Context(42); CONTEXT.current; // 42 CONTEXT.inject(77, () => { CONTEXT.current; // 77 CONTEXT.inject(null, () => { CONTEXT.current; // 42 }); }); ``` === "No Build" ```jsx import { Context } from "./rvx.js"; const CONTEXT = new Context(42); CONTEXT.current; // 42 CONTEXT.inject(77, () => { CONTEXT.current; // 77 CONTEXT.inject(null, () => { CONTEXT.current; // 42 }); }); ``` ## Components When rendering content, you can use the `<Inject>` component with JSX or the functions specified above: === "JSX" ```jsx import { Inject, Context } from "rvx"; const MESSAGE = new Context<string>(); <Inject context={MESSAGE} value="Hello World!"> {() => <h1>{MESSAGE.current}</h1>} </Inject> // Or inject multiple contexts: <Inject states={[MESSAGE.with("Hello World!"), ...]}> {() => <h1>{MESSAGE.current}</h1>} </Inject> ``` === "No Build" ```jsx import { Context, e } from "./rvx.js"; const MESSAGE = new Context(); MESSAGE.inject("Hello World!", () => { return e("h1").append(MESSAGE.current); }); Context.inject([MESSAGE.with("Hello World!"), ...], () => { return e("h1").append(MESSAGE.current); }); ``` ## Async Code Since contexts rely on the synchronous call stack, they don't automatically work with async code: === "JSX" ```jsx import { Context } from "rvx"; const MESSAGE = new Context<string>(); MESSAGE.inject("Hello World!", () => { MESSAGE.current; // "Hello World!" queueMicrotask(() => { MESSAGE.current; // undefined }); }); ``` === "No Build" ```jsx import { Context } from "./rvx.js"; const MESSAGE = new Context(); MESSAGE.inject("Hello World!", () => { MESSAGE.current; // "Hello World!" queueMicrotask(() => { MESSAGE.current; // undefined }); }); ``` You can wrap functions to always be called in the current context to fix this manually: === "JSX" ```jsx MESSAGE.inject("Hello World!", () => { MESSAGE.current; // "Hello World!" queueMicrotask(Context.wrap(() => { MESSAGE.current; // "Hello World!" })); }); ``` === "No Build" ```jsx MESSAGE.inject("Hello World!", () => { MESSAGE.current; // "Hello World!" queueMicrotask(Context.wrap(() => { MESSAGE.current; // "Hello World!" })); }); ```