kcmr / context-provider

A context Provider and Consumer for Web Components
context-provider.vercel.app
MIT License
12 stars 2 forks source link

Context Provider & Consumer for Web Components

npm version Build Status Commitizen friendly semantic-release codecov Dependency status

Allows to use context Provider and Consumer components in a similar manner than the Context in React.

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

This can be useful for properties or state that is considered global to an application like the language, user information or media query breakpoints.

The value of the nearest Provider component is available to Consumer components in their context property regardless the level of nesting without the need to pass properties from parents to children.

Usage

Install

npm i @kuscamara/context-provider

Create a Provider

import { createContextProvider } from '@kuscamara/context-provider';

const globals = /* App globals */;
const ContextProvider = createContextProvider(globals);

window.customElements.define('context-provider', ContextProvider);

Add Consumer capabilities to a component

import { contextConsumerMixin } from '@kuscamara/context-provider';

class MyComponent extends contextConsumerMixin(HTMLElement) {
  render() {
    // do whatever you need with your context property
    return `<p>My context is ${this.context}</p>`;
  }
}

Set and change the Provider value

You must set the property, not the attribute. LitElement is used in this example to emphasize the property binding syntax (.property).

import { LitElement, html } from 'lit-element';

class App extends LitElement {
  static get properties() {
    return {
      globals: { type: Object },
    };
  }

  constructor() {
    super();
    this.globals = {
      lang: 'es',
    };
  }

  onLangChange(event) {
    this.globals = {
      ...this.globals,
      lang: event.detail.value,
    };
  }

  render() {
    return html`
      <context-provider .value=${this.globals}>
        <lang-selector @change=${this.onLangChange}></lang-selector>

        <!-- context-consumer has access to the provider value in its "context" property -->
        <context-consumer></context-consumer>
      </context-provider>
    `;
  }
}

Subscribe to changes in the Provider value from consumers

The onContextChanged() hook should be implemented by components using the Consumer mixin that want to react to changes in the value property of the Provider.

import { contextConsumerMixin } from '@kuscamara/context-provider';

class MyComponent extends contextConsumerMixin(HTMLElement) {
  // Called when the Provider value changes
  onContextChanged() {
    this.render();
  }

  render() {
    return `<p>My context is ${this.context}</p>`;
  }
}

Development

This repository uses Conventional Commits to automatically generate the releases and Changelog.

Acknowledgments

The Provider and Consumer are highly inspired by Masquerades, a library for styled Web Components.

License

This project is licensed under the MIT License.