All files / react-tao/src withContext.js

100% Statements 9/9
100% Branches 4/4
100% Functions 4/4
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48                                                    11x 1x   10x 10x 6x 1x         2x       6x     6x      
import React from 'react';
 
import createContextHandler from './createContextHandler';
 
/** @typedef {import('./helpers').TrigramProps} TrigramProps */
/**
 * @template [S=any]
 * @typedef {import('./useTaoDataState').TaoDataHandler<S>} TaoDataHandler
 */
 
/**
 * HOC factory: subscribes to trigram-driven handler state and injects it
 * into the wrapped component as the `data` prop (all other props pass
 * through unchanged).
 * @template [S=any]
 * @param {?TrigramProps} tao - trigram(s) to subscribe to (array parts
 *        multi-match; null/empty = one all-wildcard subscription)
 * @param {TaoDataHandler<S>} handler - derives the next state per signal
 *        (`(tao, data, set, current) => …`); required
 * @param {S|(() => S)} [defaultValue] - initial state or lazy initializer
 * @returns {(ComponentToWrap: import('react').ComponentType<*>) => import('react').FunctionComponent<*>}
 *          HOC rendering `ComponentToWrap` with `data` = the current handler
 *          state plus all passthrough props
 * @throws {Error} when `handler` is not a function
 */
export default function withContext(tao, handler, defaultValue) {
  if (typeof handler !== 'function') {
    throw new Error('withContext `handler` must be a function');
  }
  const WrappingContext = createContextHandler(tao, handler, defaultValue);
  return (ComponentToWrap) => {
    const wrappedComponent = (props) => (
      <WrappingContext.Provider>
        <WrappingContext.Consumer>
          {/* value =>
            React.cloneElement(ComponentToWrap, { data: value, ...props })
          */}
          {(value) => <ComponentToWrap data={value} {...props} />}
        </WrappingContext.Consumer>
      </WrappingContext.Provider>
    );
    wrappedComponent.displayName = `withContext(${
      ComponentToWrap.displayName || ComponentToWrap.name
    })`;
    return wrappedComponent;
  };
}