Skip to content

Instantly share code, notes, and snippets.

@loganvolkers
Last active September 15, 2020 15:41
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 loganvolkers/9453eb3b92bb69454f874f874f586303 to your computer and use it in GitHub Desktop.
Save loganvolkers/9453eb3b92bb69454f874f874f586303 to your computer and use it in GitHub Desktop.
Context for Stencil
@Component({
tag: 'stencil-consumer',
})
export class StencilConsumer {
@Prop() renderer: any;
@State() context: Record<string, any>;
componentWillLoad(){
console.log("Will load")
}
render() {
if (!this.context) {
return "No context";
}
return <div>
Context: {JSON.stringify(this.context)}
{this.renderer(this.context)}
</div>
}
}
context.connectToProps(StencilConsumer, (c, next) => (c.context = next));
@Component({
tag: 'stencil-provider',
})
export class StencilProvider {
provider = context.provide(this, this.STENCIL_CONTEXT);
render() {
return <slot />;
}
}
import { getElement } from '@stencil/core';
import { createContext as rawCreate, ContextProvider } from 'dom-context';
const LISTENER = Symbol('listener');
export interface Constructor<T> {
new (...args: any[]): T;
}
export type ContextHandler<T, C> = (component: C, context: T) => unknown;
export function createContext<T>(name: string, initial?: T) {
const raw = rawCreate(name, initial);
function connectToProps<C>(
component: Constructor<C>,
handler: ContextHandler<T, C>,
) {
const ComponentPrototype = component.prototype;
const { componentWillLoad, disconnectedCallback } = ComponentPrototype;
ComponentPrototype.componentWillLoad = function () {
console.log('Consumer load');
const element = getElement(this);
const onChange = (val: T) => handler(this, val);
const listener = new raw.Listener({
element,
onChange,
onStatus: (st) => console.log("Status", st),
});
this[LISTENER] = listener;
listener.start();
componentWillLoad && componentWillLoad.call(this);
};
ComponentPrototype.disconnectedCallback = function () {
console.log('Disconnected Consumer');
this[LISTENER] && this[LISTENER].stop();
disconnectedCallback && disconnectedCallback.call(this);
};
}
function provide<C>(component: C, initialState?: T): ContextProvider<T> {
const el = getElement(component);
const element = getElement(component);
// console.log('Initial state', initialState);
const provider = new raw.Provider({
element,
//@ts-ignore
initialState: initialState,
});
console.log('Wired up to', element);
provider.start();
const connectedCallback = component['connectedCallback'];
component['connectedCallback'] = function () {
console.log('Provider start');
provider.start();
if (connectedCallback) {
connectedCallback.call(component);
}
};
const disconnectedCallback = component['disconnectedCallback'];
component['disconnectedCallback'] = function () {
console.log('Provider stop');
provider.stop();
if (disconnectedCallback) {
disconnectedCallback.call(component);
}
};
return provider;
}
const stencil = {
...raw,
connectToProps,
provide,
};
return stencil;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment