🌊

react 汎用provider

2023/12/20に公開

概要

reactの汎用Provider。Providerを色々コンポーネント作るときに使うことがあるかと思いますが、いちいちProviderとかContextを書いていると面倒なので汎用関数を定義します。

実装

function createContext<ContextValueType extends object | null>(
  rootComponentName: string,
  defaultContext?: ContextValueType
) {
  const Context = React.createContext<ContextValueType | undefined>(defaultContext)

  function Provider(props: ContextValueType & { children: React.ReactNode }) {
    const { children, ...context } = props

    const value = React.useMemo(() => context, Object.values(context)) as ContextValueType
    return <Context.Provider value={value}>{children}</Context.Provider>
  }

  function useContext(consumerName: string) {
    const context = React.useContext(Context)
    if (context) return context
    if (defaultContext !== undefined) return defaultContext

    throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``)
  }

  Provider.displayName = rootComponentName + 'Provider'
  return [Provider, useContext] as const
}

//使い方。通常のProviderとuseContextの使い方をあとはすれば良い
const [ AccordionProvider, useAccordionContext ] = createContext<AccordionContextValueType>(ACCORDION_NAME)

参考

https://github.com/radix-ui/primitives

Discussion