useContext フックで Consumer をリファクタリングする

この記事では「React Context API を使う簡単な例」から「useState フックでデータを更新する Provider と Consumer を実装する」にかけて作ったプログラムをリファクタリングします。

ここでは useContext フックを利用して、より簡潔に Consumer を書き直します。

useContext フックに Context を渡すと、Consumer で受け取れる value を直ちに受け取ることができます。 このため Consumer 要素を使って value を取得する、というステップが不要になります。

FruitContext.js は次のように書き換えられます。

import React, { createContext, useState } from 'react';
import { fruitData } from './fruit-data';

export const FruitContext = createContext();

export const FruitProvider = ({ children }) => {
  const [fruits, setFruits] = useState(fruitData);
  const addFruit = (newFruit) => setFruits([...fruits, newFruit]);
  const removeFruit = (s) => setFruits(fruits.filter((fruit) => fruit !== s));

  return (
    <FruitContext.Provider value={{ fruits, addFruit, removeFruit }}>
      {children}
    </FruitContext.Provider>
  );
};

//export const FruitsConsumer = FruitsContext.Consumer;

4 行目で再び FruitContextをエクスポートしています。useContext フックはコンテキストを受け取るためです。

18 行目の FruitsConsumerを削除します。Consumer を使う必要がないためです。

これまで Consumer を明示的に使っていた App.jsは、useContext フックを利用すると 次のように書き直せます。

import React, { useContext } from 'react';
import './App.css';
import { FruitContext } from './FruitContext';

function App() {
  const { fruits, addFruit, removeFruit } = useContext(FruitContext);

  return (
    <>
      <h1>Fruits</h1>
      <div>
        <button onClick={() => addFruit(`Fruit ${fruits.length + 1}`)}>
          Add
        </button>
      </div>
      <ul>
        {fruits.map((fruit, i) => (
          <li key={i} onClick={() => removeFruit(fruit)}>
            {fruit}
          </li>
        ))}
      </ul>
    </>
  );
}

export default App;

FruitConsumer 要素は全く不要になりました。このため、コンポーネントのネストが一段下がり、シンプルになっています。

その代わり、6 行目で useContext フックを利用して、コンテキストから直ちに Provider でセットした value を取得できています。

以上で、だいぶシンプルになってきました。

次の記事「カスタムフックで Context をエクスポートしないようリファクタリングする」ではカスタムフックを実装することで、もう少しだけ簡略化を行います。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 React 入門