【React】あーそーゆーことねuseEffect完全に理解した【Hook】
この記事は
Calendar for React | Advent Calendar 2021 - Qiita
の13日目です。
12日目は@sonishimuraさんのこちらの記事でした。
zenn.dev
警告文とか結構無視して
開発続けちゃいがちなので、
勉強して改善させていただきます!
改めましてこんにちは!nomurabbitです。
この記事では、ReactのHookのひとつ、
useEffectについて紹介したいと思います。
React Hookって
イメージをつかむのが難しいですよね。
一緒に勉強していきましょう!
useEffectと実行タイミング
useEffectの概要を把握するために、
実行タイミングから理解するのがよいと思います。
Reactはレンダリング、差分計算、DOMの更新という
3つのプロセスを経て画面を表示しますが、
useEffectはDOMの更新のさらに後に実行されます。
例えばこんなプログラムを実行すると…
import React, { useEffect, useState } from 'react'; import ResponsiveDrawer from '../components/layout/ResponsiveDrawer'; const Home = () => { const [count, setCount] = useState(0); useEffect(() => { //document.title = "effect"; }); document.title = "rendering"; return ( <ResponsiveDrawer> <div> <p>It's amplify test / home page.</p> </div> </ResponsiveDrawer> ); } export default Home;
実行結果はこんな感じ。
ページのタイトルは rendering となります。
次にuseEffectのコメントアウトを外して
実行してみると…。
import React, { useEffect, useState } from 'react'; import ResponsiveDrawer from '../components/layout/ResponsiveDrawer'; const Home = () => { const [count, setCount] = useState(0); useEffect(() => { document.title = "effect"; }); document.title = "rendering"; return ( <ResponsiveDrawer> <div> <p>It's amplify test / home page.</p> </div> </ResponsiveDrawer> ); } export default Home;
このように
ページのタイトルは effect となります。
useEffectの実行タイミングについて、
なんとなくおわかりいただけたでしょうか?
useEffectの利用法
useEffectの目的が
実行タイミングをずらすだけなら、
ソースの最後に記述すればいいのでは?
import React, { useEffect, useState } from 'react'; import ResponsiveDrawer from '../components/layout/ResponsiveDrawer'; const Home = () => { const [count, setCount] = useState(0); document.title = "rendering"; document.title = "effect"; return ( <ResponsiveDrawer> <div> <p>It's amplify test / home page.</p> </div> </ResponsiveDrawer> ); } export default Home;
はい、その疑問はごもっともです。
この例では実行結果は同じになりますね。
useEffectを使っても使わなくても
ページのタイトルはeffectです。
ここで今一度、
公式のチュートリアルを見てみましょう。
副作用 (effect) フック により、
関数コンポーネント内で副作用を実行することが
できるようになります。
とあります。言い換えると、
関数コンポーネント内で副作用を実行するときは
useEffectを使いましょう。
ということです。
では、ここでいう副作用とは何のことでしょうか?
残念ながらReactのチュートリアルからは
副作用の定義は読み取れませんでした。
しかし、一般的に副作用というと、
関数型の世界で下記のような概念で
語られることが多いと思います。
- 関数の外に影響を与えるもの
- 関数の引数以外で、戻り値に影響を与えるもの
ページのタイトルを変更する例は1.に該当します。
また、関数コンポーネントからAPIを呼び出す場合は
2.に該当します。
これら副作用を
事故なく実行するための仕組みが
useEffectだと理解できます。
useEffectの使用例
ここからはuseEffectの使用例をいくつかあげていきます。
まずはDOMの書き換えです。
関数の外に影響を与える副作用に該当します。
import React, { useEffect, useState } from 'react'; import ResponsiveDrawer from '../components/layout/ResponsiveDrawer'; const Home = () => { const [count, setCount] = useState(0); useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <ResponsiveDrawer> <div> <p>It's amplify test / home page.</p> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> </ResponsiveDrawer> ); } export default Home;
※少しわかりにくいですが、
ページのタイトルが更新されています。
次にAPIの呼び出し(UPDATE系)です。
こちらも関数の外に影響を与える副作用に該当します。
import React, { useEffect, useState } from 'react'; import axios from 'axios'; import ResponsiveDrawer from '../components/layout/ResponsiveDrawer'; const Home = () => { const [msg, setMsg] = useState(""); const apiUrl = ""; useEffect(() => { if(msg !== ""){ axios.post(apiUrl, { message: msg },{ headers: { 'Content-Type': "text/plain" }, }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); } },[msg]); return ( <ResponsiveDrawer> <div> <p>It's amplify test / home page.</p> <button onClick={() => setMsg("Hello nomurabbit")}> Click me </button> </div> </ResponsiveDrawer> ); } export default Home;
最後にAPIの呼び出し(SELECT系)です。
こちらはAPIの結果で関数の戻り値が変わる可能性があるので、
関数の引数以外で、戻り値に影響を与えるもの副作用に該当します。
import React, { useEffect, useState } from 'react'; import axios from 'axios'; import ResponsiveDrawer from '../components/layout/ResponsiveDrawer'; const Home = () => { const [strikeout, setStrikeout] = useState(""); const [walks, setWalks] = useState(""); const [bbk, setBbk] = useState(""); const apiUrl = ""; interface IResponse { bbk: string } useEffect(() => { if(strikeout !== "" && walks !== ""){ axios.post<IResponse>(apiUrl , { "strikeout": strikeout, "walks": walks },{ headers: { 'Content-Type': "text/plain" }, }) .then(function (response) { setBbk(response.data.bbk); console.log(); }) .catch(function (error) { console.log(error); }); } },[strikeout, walks]); return ( <ResponsiveDrawer> <div> <p>It's amplify test / home page.</p> <p>bbk is {bbk}</p> <button onClick={() => {setStrikeout("60"); setWalks("42");}}> Click me </button> </div> </ResponsiveDrawer> ); } export default Home;
以上がuseEffectについての紹介となります。
なんとなくの概念だけでも
ご理解いただけましたでしょうか?
よかったら参考にしてみてください。
13日目に@ut0nさんの記事もアップされてます。
techtekt.persol-career.co.jp
流行りについていけてないなーとか
感じることがとくあるので、
こういうまとめ記事とても助かります!
14日目は@7tsunoさんの記事です。
よろしくお願いします!