member/index.js

import React from "react";
import useReducer from "../useReducer";
import * as actions from "../actions";
import makeContext from "../makeContext";
import makeGetInitialState from "../makeGetInitialState";
import makeReducer from "./makeReducer";
import makeUseMember from "../makeUseMember";
import makeUseCollection from "../makeUseCollection";
import makeFields from "../makeFields";
import makeUseSelector from "./makeUseSelector";
import defaultInitialState from "./initialState";

/** @module memberHoax.makeMemberProvider */

/**
 * @typedef {Object} MemberHoax
 * @property {function} Provider - The member context provider
 * @property {function} useMember - A react hook for
 * @property {function} useCollection - A react hook for
 * @property {function} useSelector - A react hook for
 * @property {function} useAction - A react hook for
 * @property {object} Field
 */

/**
 * makeMemberProvider factory.
 * @param {string} name - The name of the resource, will be used on the `displayName`.
 * @param {object} [options={}] - The resource options.
 * @param {object} options.initialState - The initialState of the resource, will be merged with the default member hoax initialState.
 * @param {function} options.reducer - `reducer(state, action)` An extra reducer for the resource, should return nothing on actionType mismatch, after passing through the custom reducer, it will go through the default member hoax reducer.
 * @param {object} options.actions - Extra actions, check the default hoax actions for member.
 * @return {MemberHoax} MemberHoax - what is needed for a member resource
 */

const makeMemberProvider = (
  name,
  { getInitialState, reducer: customReducer, actions: customActions } = {}
) => {
  const initState = makeGetInitialState({
    getInitialState,
    defaultInitialState
  });
  const { reducer, init } = makeReducer(initState, customReducer);

  const [StateCtx, DispatchCtx] = makeContext();
  const useMember = makeUseMember(StateCtx, DispatchCtx);
  const useCollection = makeUseCollection(StateCtx, DispatchCtx);
  const Field = makeFields(useMember);
  const { useSelector, useAction } = makeUseSelector(StateCtx, DispatchCtx);

  const MemberProvider = ({ children, initialState, extraArgument }) => {
    const [state, dispatches] = useReducer(reducer, {
      initialState,
      init,
      actions: { ...actions, ...customActions },
      extraArgument
    });

    return (
      <DispatchCtx.Provider value={dispatches}>
        <StateCtx.Provider value={state}>{children}</StateCtx.Provider>
      </DispatchCtx.Provider>
    );
  };

  MemberProvider.displayName = name;

  return {
    Provider: MemberProvider,
    useMember,
    useCollection,
    useSelector,
    useAction,
    Field,
    getInitialState: initState
  };
};

export default makeMemberProvider;