All files / react-tao/src createContextHandler.js

100% Statements 7/7
100% Branches 4/4
100% Functions 2/2
100% Lines 7/7

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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63                                                                      23x 1x       22x             16x 16x             22x   22x          
import React, { createContext } from 'react';
 
import useTaoDataState from './useTaoDataState';
 
/** @typedef {import('./helpers').TrigramProps} TrigramProps */
/**
 * @template [S=any]
 * @typedef {import('./useTaoDataState').TaoDataHandler<S>} TaoDataHandler
 */
 
/**
 * A Provider/Consumer pair bound to trigram-driven handler state.
 * @template [S=any]
 * @typedef {Object} ContextHandler
 * @property {import('react').FunctionComponent<{children?: import('react').ReactNode}>} Provider -
 *           subscribes to the trigram(s) while mounted and provides the
 *           current handler state to descendants
 * @property {import('react').Consumer<S>} Consumer - render-prop consumer of
 *           the current handler state
 */
 
/**
 * Factory returning a Provider/Consumer pair bound to trigram handler state.
 * Used by `withContext` and as a lower-level escape hatch.
 * @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) => …`); omitted = AppCon data becomes
 *        the state
 * @param {S|(() => S)} [defaultValue] - initial state or lazy initializer
 * @returns {ContextHandler<S>}
 * @throws {Error} when `handler` is given but not a function
 */
export default function createContextHandler(tao, handler, defaultValue) {
  if (handler != null && typeof handler !== 'function') {
    throw new Error('createContextHandler `handler` must be a function');
  }
 
  // Default unused when Provider always supplies value; keep null sentinel.
  const WrappingContext = createContext(/** @type {S} */ (null));
 
  /**
   * Subscribes while mounted and provides the handler state to descendants.
   * @param {{children?: import('react').ReactNode}} props
   */
  function Provider({ children }) {
    const state = useTaoDataState(tao, handler, defaultValue);
    return (
      <WrappingContext.Provider value={state}>
        {children}
      </WrappingContext.Provider>
    );
  }
  // Stryker disable next-line StringLiteral: displayName is DX-only
  Provider.displayName = 'TaoCreateContextHandlerProvider';
 
  return {
    Provider,
    Consumer: WrappingContext.Consumer,
  };
}