React Hooksを基礎から理解する 5-6 カスタムフック
カスタムフックとは
- 関数名がuseから始まる独自のフック。ほかのフックを呼び出せる関数。
- UIと切り離してロジックごとに処理を切り出すことにより、カスタムフックの使いまわしや、重複したロジックを取り除くことができる。
カスタムフックの作成例
ベースとなるコンポーネント
import React, { useState } from "react";
const CounterText = (props) => <p>現在のカウント数: {props.count}</p>;
const INITIAL_COUNT = 0;
const Counter = () => {
const [count, setCount] = useState(INITIAL_COUNT);
const countAdd = () => setCount((prevCount) => prevCount + 1);
const countSub = () => setCount((prevCount) => prevCount - 1);
const countReset = () => setCount(INITIAL_COUNT);
return (
<>
<CounterText count={count} />
<button onClick={countAdd}>ボタン +1</button>
<button onClick={countSub}>ボタン -1</button>
<button onClick={countReset}>リセット</button>
</>
);
};
export default function App() {
return <Counter />;
}
ロジックをフックに切り出す
import React, { useState } from "react";
const CounterText = (props) => <p>現在のカウント数: {props.count}</p>;
const INITIAL_COUNT = 0;
// フックを定義
const useCounter = (initialCount) => {
const [count, setCount] = useState(initialCount);
const countAdd = () => setCount((prevCount) => prevCount + 1);
const countSub = () => setCount((prevCount) => prevCount - 1);
const countReset = () => setCount(initialCount);
return { count, countAdd, countSub, countReset };
};
const Counter = () => {
// カスタムフックの利用
const { count, countAdd, countSub, countReset } = useCounter(INITIAL_COUNT);
return (
<>
<CounterText count={count} />
<button onClick={countAdd}>ボタン +1</button>
<button onClick={countSub}>ボタン -1</button>
<button onClick={countReset}>リセット</button>
</>
);
};
export default function App() {
return <Counter />;
}
カスタムフックを利用する
- カウンターカスタムフック
useCounter.js
import React, { useState } from "react";
export const useCounter = (initialValue) => {
const [count, setCount] = useState(initialValue);
const countAdd = () => setCount((prevCount) => prevCount + 1);
const countSub = () => setCount((prevCount) => prevCount - 1);
const countReset = () => setCount(initialValue);
return { count, countAdd, countSub, countReset };
};
- 「現在のカウント数」表示コンポーネント
CounterText.js
import React from "react";
export const CounterText = ({ count }) => {
return (
<p>
現在のカウント数: <b>{count}</b>
</p>
);
};
- カウンター部分(タイトル、ボタン)
Counter.js
import React from "react";
import { useCounter } from "./useCounter";
import { CounterText } from "./CounterText";
export const Counter = ({ counterName }) => {
const { count, countAdd, countSub, countReset } = useCounter(0);
return (
<p>
<h1>{counterName}</h1>
<CounterText count={count} />
<button onClick={countAdd}>ボタン +1</button>
<button onClick={countSub}>ボタン -1</button>
<button onClick={countReset}>リセット</button>
</p>
);
};
- 全体
App.js
import { Counter } from "./Counter";
import "./styles.css";
export default function App() {
return (
<div>
<Counter counterName="カウンターA" />
<Counter counterName="カウンターB" />
<Counter counterName="カウンターC" />
</div>
);
}