カスタムフック
カスタムフックを使う理由はコンポーネント分けと同じで、use系も使い回しができるようになる。
コンポーネント分けするよりもUIの自由度が高い!
カスタムフックを使用するときに気をつけること
・hooksの命名はuse
から始めるべき(マニュアルにそう書いてある)。hooksと他の関数を見分けやすくするため。
・hooksはrerutnより前に記述する。
・hooksはJavaScriptの関数ではなく、Reactにおけるコンポーネント内で呼び出す。
カスタムフックの利用方法
import { useEffect } from 'react';
export const useBgLightBlue = () => {
useEffect(() => {
console.log('こいつが実行されるよ');
return () => {
console.log('アンマウントも実行されるよ');
}
}, []);
}
import { useCallback, useState } from 'react';
export const useInputArray = () => {
const [text , setText] = useState("");
const [array, setArray] = useState([1, 2, 3]);
const handleChange = useCallback((e) => {
setText(e.target.value);
}, []);
const handleAdd = useCallback(() => {
setArray((array) => {
if (array.some((item) => item === text)) {
alert("既に存在しています");
return array;
}
return [...array,text];
});
}, [text])
return { text , array , handleChange , handleAdd};
}
import { useCallback, useState } from 'react';
export const useCounter = () => {
const [foo, setFoo] = useState(1);
const [isShow, setIsShow] = useState(true);
const handleClick = useCallback(() => {
setFoo(foo => foo + 1);
},[]);
const handleDisplay = useCallback(() => {
setIsShow((isShow)=> !isShow);
}, []);
return { foo , isShow , handleClick , handleDisplay};
}
上記三つのコンポーネントが機能ごとにhooks分けされたもの。
import { useCounter } from 'src/hooks/useCounter';
import { useInputArray } from 'src/hooks/useInputArray';
import { useBgLightBlue } from 'src/hooks/useBgLightBlue';
export default function Home() {
const { foo, isShow, handleClick, handleDisplay } = useCounter();
const { text, array, handleChange , handleAdd } = useInputArray();
useBgLightBlue();
return (
<>
{isShow ? <h1>{foo}</h1> : null}
<button
onClick={handleClick}>
ボタン
</button>
<button
onClick={handleDisplay}
>
{isShow ? "非表示" : "表示"}
</button>
<input type="text" value={text} onChange={handleChange} />
<button onClick={handleAdd}>追加</button>
<ul>
{array.map((item) => {
return <li key={item}>{item}</li>;
})}
</ul>
</>
)
}
この三つのコンポーネントをindex.jsxで読み込む。
なぜコンポーネント分けではなく、カスタムフックを使用するのか
それはカスタムフックの方がUIの自由度が高いため。
コンポーネントのようにUlで分けている分けではなく、あくまでも機能で分けているている。
そのため使い回したいがUlが一致していないときにカスタムフックが役に立つ。
だから「どこにこの機能を付与してもUIは統一!!」という場合はコンポーネント分けしてもいいのかなと思う。
(カスタムフックの方が「どんな機能を持っているのか」は把握しやすくなるけどね)
リフトアップ
上記でuse系をさまざまなファイルで使用できるようになったけど、状態の維持はできない。
例えばカウンターで5にしたけど、ページ遷移をしたら1に戻ってしまう。理由はconst [foo, setFoo] = useState(1)
が再度読み込まれてしまい、初期値に戻るから。
そこで利用するのが_app.jsx!
_app_jsxでpropsとして渡したものは各ページでpropsとして受け取れる。
これを利用して、状態を複数ページで共有することができる。
import '@/styles/globals.css'
//インポート
import { useCounter } from 'src/hooks/useCounter';
import { useInputArray } from 'src/hooks/useInputArray';
import { useBgLightBlue } from 'src/hooks/useBgLightBlue';
export default function App({ Component, pageProps }) {
//useCounterで設定した変数や初期値をcunterに代入。
const counter = useCounter();
const inputArray = useInputArray();
useBgLightBlue();
return (
//counterの中身を展開してpropsとして渡す
<Component {...pageProps} {...counter} {...inputArray} />
)
}
export default function Home(props) {
//オブジェクトを分割代入しているので、順不同。
const { count, isShow, handleClick, handleDisplay,text, array, handleChange , handleAdd } = props;