@wcom/context v2.7.0
@wcom/context
Introduction
The inner workings and implementation are thanks to @furf.
This library enables data to be passed down component trees without having to pass props down
manually. This library is expected to be used with TypeScript,
make sure to set experimentalDecorators
to true
in tsconfig.json
.
This library currently does not work with Stencil anymore, any PR is welcomed to add support!
Install
# npm
$: npm install @wcom/context
# yarn
$: yarn add @wcom/context
# pnpm
$: pnpm install @wcom/context
Usage
If you've used React.ContextProvider
before you should already have the concepts down. Simply when
we create a context we receive a provide
and consume
decorator. Each context can only have a single
provider who is responsible for updating the current value. However, each context can have many
consumers who simply listen for updates on when the value is changed. A context can be any
data type such as a string
, boolean
, array
, object
etc.
Important: You might be familiar with this pattern by now but do no update arrays or objects in-place
with methods like array.push()
or object[key] = value
, simply because this will mean the
equality check will never be false
so no provider update will be emitted. You can update an
array like so array = [...array, 'newValue']
and object like so object = { ...object, [key]: value }
.
Here's a simple diagram:
- Provider (Let's pretend here we are providing some context)
- Child A
- Child B (Here we can consume that context without passing a prop from Provider -> A -> B).
- Child A
One last thing to keep in mind is that a consumer will connect to it's nearest provider, for example:
- Provider (Let's pretend here we are providing some context)
- Child A
- Provider (Here we are providing the same context)
- Child B (This will consume the parent provider instead of the Provider higher in the tree).
- Provider (Here we are providing the same context)
- Child A
createContext<T>(defaultValue T): Context<T>
This is the bread and butter of this library. It simply creates a new Context
which looks
like this:
interface Context<T> {
provide(): PropertyDecorator
consume(): PropertyDecorator
defaultValue?: T
}
- Let's create our context...
import createContext from '@wcom/context';
export const myContext = createContext(10);
- Setup a provider...
import { myContext } from './context';
class MyProvider extends HTMLElement {
@myContext.provide()
someContext = myContext.defaultValue;
// Setup slot etc. ...
// Update context by simply setting new values.
onUpdateContext() {
this.someContext = 20;
}
}
- Setup a consumer...
import { myContext } from './context';
class MyConsumer extends HTMLElement {
// This will now be kept in-sync with the value in `MyProvider`.
@myContext.consume()
someContext = myContext.defaultValue;
// ...
}
- Implementation in DOM...
<my-provider>
<my-consumer></my-consumer>
</my-provider>
And you're done 🎉 That's all there is to it.
Lit Example
The usage is exactly the same as above except you might want to trigger a re-render on changes,
so set a @internalProperty
decorator accordingly like so...
import { myContext } from './context';
import { internalProperty, LitElement } from 'lit-element';
class MyComponent extends LitElement {
@internalProperty()
@myContext.consume()
someContext = myContext.defaultValue;
// ...
}
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago