カスタムフックで Context をエクスポートしないようリファクタリングする
この記事では「React Context API を使う簡単な例」から「useContext フックで Consumer をリファクタリングする」にかけて作ってきたプログラムをリファクタリングします。
ここではカスタムフックを実装することで、Context も外部にエクスポートしないで済むようにします。
カスタムフックと言っても特別なコンポーネントがあるわけではありません。単に useContext を少しラップするだけです。
これまでFruitContext.jsとして作ったきたファイルは、fruit-hooks.jsという名前に変更します。
fruit-hooks.jsの中身は次のようにします。
import React, { createContext, useState, useContext } from 'react';
import { fruitData } from './fruit-data';
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 useFruits = () => useContext(FruitContext);
4 行目を変更して、FruitContets のエクスポートをやめます。
18 行目で useContext フックをラップして、 useFruits というフックを作りエクスポートします。
この部分が「カスタムフック」と呼んでいた部分です。たった一行の小さな変更です。しかしこれによって、Context も Consumer もエクスポートしなくて済むようになります。
カスタムフックを使う App.jsは次のようになります。
import React from 'react';
import { useFruits } from './fruit-hooks';
import './App.css';
function App() {
const { fruits, addFruit, removeFruit } = useFruits();
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;
2 行目で useFruitsカスタムフックを取り込んでいます。
6 行目で useFruits を呼ぶことで、Consumer で受け取れる value を受け取っています。
その他の部分は一緒です。