preact-context icon indicating copy to clipboard operation
preact-context copied to clipboard

Make warning optional: Consumer used without a Provider

Open Download opened this issue 6 years ago • 3 comments

I am getting this warning in the console:

Consumer used without a Provider

The message is clear enough, but in my case this is not an issue and I would like to suppress this warning.

I'll describe my use case below and show some example code, but the gist of it is: in my case, the use of context is optional and it is expected that it might not be provided. So I would like the option to suppress the warning.

Would you accept a PR? EDIT: Too late, I already created one :) #25

Background

I am using preact-context to create a theming solution based on CSS modules. The way it works is that the components will by default render the default class names, but you can load the CSS via CSS Modules and pass the module def to a Provider and the components will pick it up and use the modified class names.

The way I did this was to have a default definition in each component that contains the unmodified class names just like they appear in my CSS.

E.g:

const defaultClasses = { 'test': 'test' }

After loading the CSS through CSS Modules, this will produce a module definition with mangled class names (to provide scoping), that looks like this:

const classes = import('./some/styles.css');
// classes == { 'test': 'test_23rfT4' }

The user of my library can wrap the components in a theme Provider and provide the mangled names so the components will use those names i.s.o the default ones.

The components all use a Consumer defined in a common file and when the user needs a Provider, he gets it from this same file:

theme.jsx

import { h } from 'preact'
import { createContext } from 'preact-context'

export const Theme = createContext({})
export const Provider = Theme.Provider
export const Consumer = Theme.Consumer

export default { Theme, Provider, Consumer }

The components use the Consumer to try to get the property classes from the context, defaulting it to an empty object. They then merge the classes over the defaultClasses and use the resulting definition:

card.jsx

import { h } from 'preact'
import defaultClasses from 'solids/card/classes'
import { createHelper } from '../style-classes'
import { Consumer } from '../theme'

export const Card = (props = {}) => {
  const {
    // show an outlined card
    outlined = false,
    children,
    // other attributes
    ...attributes
  } = props

  return (
    <Consumer>{({ classes = {}, scope = 'local' }) => {

      classes = { ...defaultClasses, ...classes }
      let classNames = createHelper(classes, scope)
      attributes.className = classNames(classes.card, {
      [attributes.className || attributes.class]: attributes.className || attributes.class,
        [classes.outlined]: outlined,
      })

      return (
        <div {...attributes}>
          {children}
        </div>
      );
    }}</Consumer>
  )
}

export default Card;

This all works like a charm, except that I get this annoying warning, even in the production build.

Download avatar Jan 14 '19 20:01 Download

It might be helpful to look at some actual projects, but I can understand if it's too much :)

  • solids (contains the .scss files and .js files with the default class names in them)
  • preact-solids (contains the Preact components that import the default class names from the js files)
  • solids-www (contains an example app that uses CSS Modules and a provider to override the class names)

Download avatar Jan 14 '19 20:01 Download

Thanks for the PR. I'll try to merge it as soon as possible

valotas avatar Jan 14 '19 23:01 valotas

I created a new PR. I processed your feedback and implemented the log option as well.

Download avatar Jan 18 '19 21:01 Download