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 をエクスポートしないようリファクタリングする」ではカスタムフックを実装することで、もう少しだけ簡略化を行います。