はじめに
今回からReact Hooksについてざっくりまとめていこうと思います。
その第一回目になります。
useState
useStateフックは、React本体に関数コンポーネント専用の保存領域を作成してもらい、そこにあるデータを読み書きできるフックです。
構文
const[state, state更新関数]=useState(stateの初期値);
使用例
import React, { useState } from "react";
export default function App() {
const [count, setCount] = useState(10);
const decrement = () => {
setCount(count - 1);
};
const increment = () => {
setCount(count + 1);
};
return (
<>
<p>Count: {count}</p>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</>
);
}
useEffect
コンポーネントに副作用を追加するhookです。
副作用とは下記のようなものを指します。
・DOMの操作
・APIとの通信
・非同期処理 など...
このフックを実行すると、コンポーネントのレンダー後かアンマウント後に、副作用を実行させることができます。
ちなみに、アンマウントというのは、コンポーネントをDOMから削除して破棄することです。「副作用」のイメージが掴みづらいかもしれませんが、「コンポーネントのレンダー後かアンマウント後に何らかの処理を実行させたい時に利用する認識です。
つまり、useEffectは「すぐは実行されず、関数の実行タイミングをReactのレンダリング以降まで遅らせるフック」になります。
構文
useEffect(副作用,依存配列);
依存配列とは、副作用が依存している値が格納された配列です。
引数の渡し方によって副作用が実行されるタイミングは異なります。
// 副作用を毎回実行する
useEffect(() => {
console.log('completed render');
});
// 副作用に依存する値を更新したときのみ副作用を実行する
useEffect(() => {
console.log('completed render');
}, [message]);
// 副作用をレンダー後に一度だけ実行する
useEffect(() => {
console.log('completed render');
}, []);
クリーンアップ関数
副作用内で関数を返すと、その関数はコンポーネントがアンマウントもしくは、再実行した時に実行される関数。
下記のように関数を返すとコンポーネントがアンマウントもしくは、再実行した時にconsole.log('cleanup')が実行されます。
useEffect(() => {
return () => {
console.log('cleanup');
}
});
使用例
import React, { useState, useEffect } from "react";
export default function App() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(document.getElementById("effectHook").innerText);
});
return (
<div>
<p id="effectHook">You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>click</button>
</div>
);
}
useRef
refオブジェクト(React.createRefの戻り値)を返すフックです。
JSXのrefプロパティにuseRefで作成した参照を渡してやることで、、DOMの参照や、コンポーネント内で値を保持できます。
「値を保持する」という点に関してはuseStateと同じです。
しかし、useStateとは異なり、useRefで生成した値を更新してもコンポーネントは再レンダーされません。
そのため、レンダーには関係ないstateを扱いたい時(コンポーネント内で値を保持したいが、値を更新してもコンポーネントを再レンダーしたくないとき)などに利用します。
構文
constrefオブジェクト=useRef(初期値);
useRefの引数に渡した値が、refオブジェクトのcurrentプロパティの値になります。
そのため次のようにuseRefに0を渡すと、refオブジェクトのcurrentプロパティの値は0になります。
const count = UseRef(0);
console.log(count.current) // 0
// currentプロパティの値を更新
// refオブジェクトを更新してもコンポーネントは再レンダーされない
count.current = count.current + 1;
また、refオブジェクトはコンポーネントが存在している間、ずっと存在し続けます。
コンポーネントが再レンダーされた後でも、参照するrefオブジェクトは変わらないため、currentプロパティの値は保持されています。
使用例
import React, { useState, useEffect, useRef } from 'react';
export default function App() {
const [count, setCount] = useState(10);
const prevCountRef = useRef(0);
useEffect(() => {
prevCountRef.current = count;
});
return (
<>
<p>
現在のcount: {count}, 前回のcount: {prevCountRef.current}
</p>
<p>前回のcountより{prevCountRef.current > count ? '小さい' : '大きい'}</p>
<button onClick={() => setCount(Math.floor(Math.random() * 11))}>
update
</button>
</>
);
}