8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ReactのContext.Providerがいっぱいネストするのを防ぐための書き方

Posted at

Context.Providerの数が多いとネストが深くなる問題について

公式ドキュメントのの例における以下の部分

    // コンテクストの初期値を与える App コンポーネント
    return (
      <ThemeContext.Provider value={theme}>
        <UserContext.Provider value={signedInUser}>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    );
  }

これは2つのコンテキストProviderでラップしているが、これが多くなるとネストが深くなってくのが嫌だなという問題。

    // (コンテキスト名は適当)
    return (
      <ThemeContext.Provider value={theme}>
        <UserGroupContext.Provider value={{}}>
          <UserContext.Provider value={signedInUser}>
            <PlacementContext.Provider value={{}}>
              <HogeContext.Provider value={{}}>
                <FugaContext.Provider value={{}}>
                  <PiyoContext.Provider value={{}}>
                    <Layout />
                  </PiyoContext.Provider>
                </FugaContext.Provider>
              </HogeContext.Provider>
            </PlacementContext.Provider>
          </UserContext.Provider>
        </UserGroupContext.Provider>
      </ThemeContext.Provider>
    );
  }

これが嫌かどうかは個人の感じ方もあるかもしれないが、以下に示す書き方の方がすっきりする。

h1. 解決

import React from 'react';

/**
 * コンポーネントリストを入れ子にして連結したコンポーネントを返す
 * @param components
 * @returns {*|(function(...[*]): *)|(function(*): *)}
 */
const composeComponents = (...components) => {
  if (components.length === 0) {
    return (arg) => arg;
  }
  if (components.length === 1) {
    return components[0];
  }
  return components.reduce((A, B) => (props) => <A><B {...props} /></A>);
};


const ComposedProvider = composeComponents(
  (props) => <ThemeContext.Provider {...props} value={theme} />,
  UserGroupContext.Provider,
  (props) => <UserContext.Provider {...props} value={signedInUser} />,
  HogeContext.Provider,
  FugaContext.Provider,
  PiyoContext.Provider,
);

/* (途中省略) */
    return (
      <ComposedProvider>
        <Layout />
      </ComposedProvider>
    );


コンポーネントをreduceを使って連結する関数を用意しておいて、連結結果でラップするように書くとキレイだし、順番を入れ替えたりするのも楽。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?