Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9409

react-hooks 基礎

$
0
0
目次 react-hooksについて useState useEffect useRef React.memo / useCallback / useMemo useReducer Context / useContext カスタムフック 1. react-hooksについて Reactのバージョン16.8.0で追加された機能 関数コンポーネントで利用できる関数のこと クラスコンポーネントでしかできなかったこと(state管理)が、関数コンポーネントでもできるようになる クラスコンポーネントよりもコード量を減らせる ロジックを分離できるので、ロジックの再利用やテストがしやすい 2. useState state, state更新関数を返すフック state管理とは、stateの保持とstateの更新をすること import React, { useState } from "react"; //構文フォーマット const [state, state更新関数] = useState(stateの初期値); //初期値が0の「count」というstateと //「setCount」というcountを更新する関数を定義 const [count, setCount] = useState(0); const countMinus = (currentCount) => currentCount - 1; //countが-1される setCount(countMinus); 3. useEffect コンポーネントのレンダー後かアンマウント後に、副作用(何らかの処理)を実行させる import React, { useState, useEffect } from "react"; //構文フォーマット useEffect(副作用, 依存配列); //コンポーネントがレンダーされるたびに副作用を実行させる //第1引数の副作用だけを渡しても動作する useEffect(() => { console.log('completed render'); }) //副作用に依存する値が更新した時だけ、副作用を実行させる useEffect(() => { console.log(message); }, [message]); //副作用を1度だけ実行させる //第2引数に空の配列を指定する useEffect(() => { console.log('completed render'); }, []); //副作用内で関数を返すと、コンポーネントがアンマウントor副作用が再実行した時に実行される //この関数のことを「クリーンアップ関数」と言う useEffect(() => { return () => { console.log('clean up'); } }); 4. useRef refオブジェクト(React.createRefの戻り値)を返すフック refオブジェクトを利用することで、DOMの参照やコンポーネント内で値を保持できる useStateとは異なり、useRefで生成した値を更新してもコンポーネントは再レンダーされない(値を更新しても、再レンダーしたくない時などに使用する) import React, { useState, useEffect, useRef } from "react"; //構文フォーマット const refオブジェクト = useRef(初期値); //useRefの引数に渡した値が、refオブジェクトのcurrent プロパティの値になる。 const count = useRef(0); console.log(count.current) // -> 0 //更新 count.current = const.current + 1; DOMの参照 useRefでDOMを参照したい場合、作成したrefオブジェクトをHTML要素のref属性に指定する必要がある //以下により、inputEl.currentでDOMを参照できる const inputEl = useRef(null); <input ref={inputEl} type="text" /> 5. React.memo / useCallback / useMemo 不要な再計算やコンポーネント再レンダーを抑えるための手段が以下の3つ React.memo コンポーネント(コンポーネントのレンダー結果)をメモ化するReactのAPI メモ化とは、計算結果を保持し、それを再利用する手法のこと import React, { useState } from "react"; //構文フォーマット React.memo(関数コンポーネント) //Helloというコンポーネントをメモ化する //これにより、前回のpropsと比較して、等価であれば再レンダーせずに、メモ化したコンポーネントを再利用する const Hello = React.memo(({ name } => { return <h1>Hello {name}</h1> }); useCallback メモ化されたコールバック関数を返すフック React.memoでメモ化したコンポーネントにuseCallbackでメモ化したコールバック関数をpropsとして渡すことで、コンポーネントの不要な再レンダーをスキップできる import React, { useState, useCallback } from 'react'; //構文フォーマット useCallback(コールバック関数, 依存配列); //countという変数を出力する関数をメモ化 const callback = useCallback(() => console.log(count), [count]); //依存している値がなければ、依存配列は空でOK const callback = useCallback(() => console.log('hello'), []); 注意点 useCallbackはReact.memoと併用するものなので、次のような使い方をしてもコンポーネントの不要な再レンダーをスキップできない React.memoでメモ化をしていないコンポーネントにuseCallbackでメモ化をしたコールバック関数を渡す useCallbackでメモ化したコールバック関数を、それを生成したコンポーネント自身で利用する useMemo メモ化された値を返すフック コンポーネントの再レンダー時に値を再利用できるため、値の不要な再計算をスキップできる import React, { useState } from 'react'; //構文フォーマット useMemo(() => 値を計算するロジック, 依存配列); //countという変数の値を2倍にした値をメモ化する const result = useMemo(() => count * 2, [count]); 6. useReducer state, dispatch(actionを送信する関数)を返すフック このフックを利用すれば、コンポーネント内でstate管理できる actionとは? アクション(何が起きたのか)とそれに付随する情報を持つオブジェクトのこと //actionの例 //ADD_TODOというアクションタイプと、それに付随する情報text:'Learning React'を持つ const action = { type: 'ADD_TODO', text: 'Learning React' } import React, { useReducer } from 'react'; //構文フォーマット //state: stateのこと //dispatch: actionを送信する関数 //reducer: 現在のstateとactionを受け取り、actionに応じて更新したstateを返す関数 const [state, dispatch] = useReducer(reducer, stateの初期値); //reducerの関数 function reducer(state, action){ if(action.type === 'INCREMENT'){ return { count: state.count + 1 }; } else { return state } } export default function App() { //stateの初期値{count: 0}で定義 const [state, dipatch] = useReducer(reducer, { count: 0 }); return ( <> <p>count: {state.count}</p> <button onClick={() => dipatch({ type: 'INCREMENT' })}>プラス</button> </> ) } useStateとの使い分け 複雑なstateを扱う場合は、useReducerを使用したほうが良い (別のstateに依存している、stateの更新のロジックが複雑、など...) 7. Context / useContext useContextは、ContextというReactの仕組みを利用するために必要なフック Context Reactにおける「Context」は、以下のいずれかを表す 1. Propsを利用せずに様々な階層のコンポーネントに値を共有するReactの仕組み 1. Propsを利用せずに様々な階層のコンポーネントに値を共有するReactのAPI 1. Contextオブジェクトのこと 1. Contextオブジェクトの値のこと Contextの利用には以下の3つが必要 * Contextオブジェクト * Provider * Consumer Contextオブジェクト React.createContextというReactのAPIの戻り値 このContextオブジェクトが保持している値をProviderで共有できる //構文フォーマット const MyContext = React.createContext(); Provider Contextオブジェクトが保持しているコンポーネントのこと(Providerコンポーネントとも言う) 共有した値はConsumerを定義することで、受け取れる import React, { createContext } from 'react'; //Contextオブジェクト const MyContext = createContext(); export default function App(){ const name='soarflat'; return( <> {/*Provider。valueプロパティの値を共有する。*/} <MyContext.Provider value={name}> {/*MyContext.Providerにラップされているので、valueプロパティの値を取得できる。*/} <Child/> </MyContext.Provider> {/*MyContext.Providerにラップされていないので、valueプロパティの値を取得できない。*/} <Brother/> </> ); } Consumer Contextオブジェクトから値を取得しているコンポーネントのこと(Consumerコンポーネントとも言う) import React, { createContext, useContext } from 'react'; //Contextオブジェクト const MyContext = createContext(); //MyContextから値を取得しているのでConsumerである function Child1(){ //<MyContext.Provider value={name}>のnameは'React'なので、textの値は'React'になる。 const text = useContext(MyContext); return <h1>{text}</h1>; } //MyContextから値を取得していないのでConsumerではない function Child2(){ return <h2>NotConsumer</h2>; } export default function App() { const name = 'React'; return ( {/*Provider。valueプロパティの値をConsumerに共有する。*/} <MyContext.Provider value={name}> <Child1/> <Child2/> </MyContext.Provider> ); } useContext Contextオブジェクトから値を取得するフック import React, { useState, useContext, createContext } from "react"; //構文フォーマット const Contextオブジェクトの値 = useContext(Contextオブジェクト) //例 //Contextオブジェクト const MyContext = createContext(); ... const context = useContext(MyContext); return ( <> <p>{context.name}</p> <button onClick={context.handleClick}>increment</button> </> ) Contextの使い所 複数のコンポーネントで共通利用したいデータがあるが、コンポーネントの数が多かったり、階層が深いので、Propsで渡すのが困難 Prop drilling問題を解消したいが、Context以外の手段でProp drilling問題を解消するのが困難 (Prop drilling問題とは、コンポーネント間でのprop受け渡しの回送が深くなってしまう問題のこと) ただし、Contextには以下のようなデメリットもある * コンポーネントがContextに依存するため、コンポーネントの再利用性が低下する * Contextオブジェクトの値はグローバルなstateなので、何も考えずに利用すると、値がどこで利用されていたり更新されているかがわかりづらくなる 具体例 * 認証情報 : ログイン情報など * テーマ : 選択しているテーマに応じて、コンポーネントに適用するスタイルを制御するために利用する * 言語 : 表示言語の切り替え 8. カスタムフック 自作のフックのこと(コンポーネントから切り出したロジックを定義した関数) カスタムフックの名前は必ずuseから始まる必要がある import React, { useState } from 'react'; //例 //カウンターのstateとstate更新ロジックを持つカスタムフック //カスタムフックの名前は必ずuseから始まる必要がある function useCounter(initialCount){ const [count,setCount] = useState(initialCount); const increment = () => { setCount(count+1); }; const decrement = () => { setCount(count1); }; return { count, increment, decrement }; } //カスタムフックを使用 function App() { const { count,increment,decrement } = useCounter(0); return( <div> <p>count:{count}</p> <button onClick={decrement}>-</button> <button onClick={increment}>+</button> </div> ); } export default App;

Viewing all articles
Browse latest Browse all 9409

Trending Articles