Skip to main content

Data providing

The context provides a way to exchange data from top to bottom (from parent to child elements) to any depth of nesting.

Context Access

The context can be accessed via the this keyword or via the second argument (React-like way)

import type { Context } from 'whatsup/jsx'

function App(this: Context) {}

// or

function App(props: {}, ctx: Context) {}

Sharing with symbols

To make data available to child components, you need a key and, of course, data :) This method uses symbols as the key.

import type { Context } from 'whatsup/jsx'

const THEME = Symbol('Access key')

function* Parent(this: Context) {
this.share(THEME, 'dark')

while (true) {
yield <Child />
}
}

function Child(this: Context) {
const theme = this.find(THEME)

return <div>Theme is {theme}</div>
}

We specifically made the parent component using a generator - most often we only need to share the data once in the component's initialization phase. The functional component would do this on every update.

It would be correct to make a child component on the generator as well, so as not to access the context on each update to get the theme value.

function* Child(this: Context) {
const theme = this.find(THEME)

while (true) {
yield <div>Theme is {theme}</div>
}
}

Excellent! But it's not reactive! Let's fix this

import type { Context } from 'whatsup/jsx'

const THEME = Symbol('Access key')

function* Parent(this: Context) {
const theme = observable('dark')
const toggleTheme = () => theme(theme() === 'dark' ? 'light' : 'dark')

this.share(THEME, theme)

while (true) {
yield (
<>
<Child />
<button onClick={toggleTheme}>Toggle theme</button>
</>
)
}
}

function* Child(this: Context) {
const theme = this.find(THEME)

while (true) {
yield <div>Theme is {theme()}</div>
}
}

And now it's reactive :)

Sharing with Context key

Context key is an alternative to a symbol key. It allows you to specify a default value.

import { Context, createKey } from 'whatsup/jsx'

const THEME = createKey('dark')

function* Parent(this: Context) {
//...
this.share(THEME, 'light')
//...
}

function* Child(this: Context) {
/*
If THEME key is not found in the context,
then the default value will be returned.
*/
const theme = this.find(THEME)
// ...
}

Sharing with constructor

We can share instances of any class and find them by constructor.

import { Context } from 'whatsup/jsx'

class Store {}

function* Parent(this: Context) {
const store = new Store()

this.share(store)

while (true) {
yield <Child />
}
}

function* Child(this: Context) {
const store = this.find(Store)

while (true) {
// ...
}
}