5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React Hooks(基本のHook)

Last updated at Posted at 2020-12-07

基本のフック

React組み込みのフックのうち、基本のフックを試していきます。

  • useState
  • useEffect
  • useContext

React Hooks(追加のHook)

useState

トグル、値の管理に使えます。
useStateを使わずに変数を定義した場合、コンポーネントの再描画時にリセットされてしまいます。
useState によって React の state の機能を関数コンポーネントに追加します。

 const [count, setCount] = useState(intialState)

トグル

src/Toggle.js
//関数コンポーネント内で state を使えるようにするため、useState をインポート
import React, { useState } from 'react'
  
//関数コンポーネントCounterを定義
const Toggle = () => {
 
  // conditionという名前のstate変数を宣言、初期値 true をセット
  const [condition, setCondition] = useState(true)
 
  // 関数toggleを作成(state変数のconditionがtrueだとtrue、falseだとfalseを返す)
  const toggle = () => setCondition(!condition)
 
  return (
 
    <>
      {/* ボタンを押すと関数toggleを実行する*/}
      <button onClick={toggle}>{condition ? 'アクティブ' : '非アクティブ'}</button>
    </>
 
  )
 
}
 
export default Toggle
src/App.js
import React from 'react'
import Toggle from './Toggle';
 
//コンポーネントApp
const App =() => {
 
  return(
 
    <>
      <Counter/>
    </>
 
  )
 
}
 
export default App

値を管理する

数値をユーザー操作で増減させる

src/Cunter.js
// 関数コンポーネント内で state を使えるようにするため、useState をインポート
import React, { useState } from 'react'
 
//関数コンポーネントCounterを定義
const Counter = () => {
 
  //定数initialState初期値として使う0を指定
  const intialState = 0
 
  //countという名前のstate変数を作成し、初期値にintialStateをセット(countを更新するときはsetCountを使う)
  const [count, setCount] = useState(intialState)
 
  return (
    <>
        {/* 現在値を表示 */}
        <p>現在の数字は{count}です</p>
 
        {/* ボタンを押すとsetCount関数でcountを更新 setCount(現在値=>現在値+変更させる値)の形にする */}
        <button onClick={() => setCount(prevCount => prevCount + 1)}>
          + 1
        </button>
 
        {/* ボタンを押すとsetCount関数でcountを更新 setCount(現在値=>現在値+変更させる値)の形にする */}
        <button onClick={() => setCount(prevCount => prevCount - 1)}>
          - 1
        </button>
 
        {/* 定数initialStateを使って、countを初期値に戻す */}
        <button onClick={() => setCount(intialState)}>初期値に戻す</button>
 
    </>
  )
}
 
export default Counter
src/App.js
import React from 'react'
import Counter from './Counter';
 
//コンポーネントApp
const App =() => {
 
  return(
 
    <>
      <Counter/>
    </>
 
  )
 
}
 
export default App

複数の値を1つのState変数で管理する

大人と子供の数を1つのstate変数(オブジェクト)でカウントします。

1つのState変数で複数の値を管理する場合、一部の値更新しても全体が上書きされてしまいます。
(新しい値を与えていない項目は値が消えてしまいます。)

そのため、スプレッド構文で一度state変数をすべて展開して、その上で更新したい値を上書きして、すべての項目を更新することが必要です。

src/Counter.js
// 関数コンポーネント内で state を使えるようにするため、useState をインポート
import React, { useState } from 'react'
 
//関数コンポーネントCounterを定義
const Counter = () => {
 
  //定数initialState初期値として使う0を指定
  const intialState = {
    adult:0,
    child:100
  }
 
  //countという名前のstate変数を作成し、初期値にintialStateをセット(countを更新するときはsetCountを使う)
  const [count, setCount] = useState(intialState)
 
  return (
    <>
      {/* 現在値の表示を表示 */}
      <p>大人は{count.adult}人です</p>
      <p>子供は{count.child}人です</p>
 
      {/* ボタンを押すとsetCount関数でcountを更新 setCount(現在値=>現在値+変更させる値)の形にする */}
      <button onClick={() => setCount({...count,adult:count.adult+1})}>
        大人 + 1
      </button>
 
      {/* ボタンを押すとsetCount関数でcountを更新 setCount(現在値=>現在値+変更させる値)の形にする */}
      <button onClick={() => setCount({...count,adult:count.adult-1})}>
        大人 - 1
      </button>
 
 
      {/* ボタンを押すとsetCount関数でcountを更新 setCount(現在値=>現在値+変更させる値)の形にする */}
      <button onClick={() => setCount({...count,child:count.child+1})}>
        子供 + 1
      </button>
 
      {/* ボタンを押すとsetCount関数でcountを更新 setCount(現在値=>現在値+変更させる値)の形にする */}
      <button onClick={() => setCount({...count,child:(count.child-1)})}>
        子供 - 1
      </button>
 
      {/* 定数initialStateを使って、countを初期値に戻す */}
      <button onClick={() => setCount(intialState)}>初期値に戻す</button>
 
    </>
  )
}
 
export default Counter
src/App.js
import React from 'react'
import Counter from './Counter';
 
//コンポーネントApp
const App =() => {
 
  return(
 
    <>
      <Counter/>
    </>
 
  )
 
}
 
export default App

useEffect

関数をレンダリング終了後に実行します。
副作用の処理(DOMの書き換え、変数代入、API通信など)に使います。

jsx
 useEffect(() => {
   console.log("レンダリングされた");
 })

レンダリング終了ごとに決まった処理を行う

src/EffectSample.js
import React, {useState, useEffect} from 'react'
 
const EffectSample = () => {
 
  //state変数cuntの作成(初期値0)
  const [count, setCount] = useState(0)
 
  //レンダリング後に実行する処理
  useEffect(() => {
    console.log("レンダリングされた");
  })
 
  return (
    <>
      <p>{`${count}回クリックされた`}</p>
 
      <button onClick={()=>{
        setCount(prevCount => prevCount + 1)
        console.log("+1された");
        }}>
        +1
      </button>
 
      <button onClick={()=>{
        setCount(0);
        console.log("resetされた");
        }}>
        リセット
      </button>
 
     </>
  )
}
 
export default EffectSample
src/App.js
import React from 'react'
import EffectSample from './EffectSample';
 
//コンポーネントApp
const App =() => {
 
  return(
 
    <>
      <EffectSample/>
    </>
 
  )
 
}
 
export default App

特定の値が変わったときだけ適用させる

useEffectの第2引数に変数を依存配列として渡すことで、変数を監視して変更があったときに適用させます。

カウントを2種類に増やし、カウントBが変化したときのみuseEffectを作動させてみます。
useEffectの第2引数に、監視する変数をセットします。

src/EffectSample.js
import React, {useState, useEffect} from 'react'
 
const EffectSample = () => {
 
  //state変数ocuntの作成(初期値0)
  const [countA, setCountA] = useState(0)
  const [countB, setCountB] = useState(0)
 
 
  //レンダリング後に実行する処理(countBが変動する結果のレンダリングに限定)
  useEffect(() => {
    console.log("カウントBが変化した");
  },[countB])
 
  return (
  <>
    <p>{`カウントAが${countA}回クリックされた`}</p>
      <div>
        <button onClick={()=>{
          setCountA(prevCount => prevCount + 1)
          console.log("カウントAが+1された");
          }}>
          +1
        </button>
 
        <button onClick={()=>{
          setCountA(0);
          console.log("カウントAがresetされた");
          }}>
          リセット
        </button>
      </div>
 
      <p>{`カウントBが${countB}回クリックされた`}</p>
      <div>
          <button onClick={()=>{
          setCountB(prevCount => prevCount + 1)
          console.log("カウントBが+1された");
          }}>
          +1
        </button>
 
        <button onClick={()=>{
          setCountB(0);
          console.log("カウントBがresetされた");
          }}>
          リセット
        </button>
      </div>
    </>
  )
}
 
export default EffectSample
src/App.js
import React from 'react'
import EffectSample from './EffectSample';
 
//コンポーネントApp
const App =() => {
 
  return(
 
    <>
      <EffectSample/>
    </>
 
  )
 
}
 
export default App

初回レンダリング時のみ実行する

useEffectの第2引数に空の配列を渡すと、初回レンダー時だけに発動させられます。

クリーンアップ

クリーンアップを必要としない副作用の例

コードが実行されたあとすぐにそのことを忘れても構わないもの

  • ネットワークリクエストの送信
  • 手動での DOM 改変
  • ログの記録

クリーンアップを必要とする副作用の例

メモリリークが発生しないようにクリーンアップが必要な処理
(何らかの外部のデータソースへの購読をセットアップするもの)

  • イベントリスナー
  • タイマー
  • 非同期でデータを取得し画面に表示する

など

クリーンアップの記述方法

  • cleanup() 関数
  • アロー関数
jsx
useEffect(() => {
  elm.addEventListener('click', () => {})
 
  // コンポーネントがアンマウントされるときに呼ばれる(アロー関数で書く場合)
  return () => {
    elm.addEventListener('click', () => {})
  }
   
  // コンポーネントがアンマウントされるときに呼ばれる(cleanup()関数で書く場合)
  //return function cleanup() {
  //  elm.addEventListener('click', () => {}
  //}
   
}, [])

useContext

Context

コンポーネントからグローバルにアクセスできるデータです。

コンポーネントツリーのデータの橋渡し

Context/Props 説明
Context 下の階層で Contextに収容されているデータにアクセスできる(すべての階層ごとに渡す必要性がなくなる)
Props バケツリレー

useContext

親からPropsで渡されなくても、Contextに入れたデータにアクセスできます。

説明
createContext コンテキスト作成
useContext コンテキストを呼び出す

Contextを共有する一番外側で値を渡します。

jsx
import React, {useContext} from 'react'
 
//context作成してexport
export const DataContext = createContext();
 
const Parent =() => {
 
  //contextで共有するデータを作成
  const data = {
     key1: '値1',
     key2: '値2'
  };
 
 
  return(
   
    {/* 共有するデータを渡す */}
    <DaraContext.Provider value={data}>
 
      <ChildComponent/>
 
    </DataContext.Provider>
     
  )
   
}

Contextを使った値の引き渡し

親→曾孫に受渡しできます。

親要素

src/App.js
// ReactからcreateContextとuseStateをimport
import React, {createContext,useState} from 'react'

//ContextA.jsのContextコンポーネントをインポート
import Child from './Child'

//createContextでContextを作成(DataContextとTextContext)してexport
export const DataContext = createContext();
export const TextContext = createContext();
 
function App() {

  //dataを作成
  const [data,setData] = useState({
    name: '山田',
    age: '20'
  });


  //textを作成
  const [text,setText] = useState('こんにちは');

  return (
    <div className='App'>

      {/*DataContext.Providerを作成、valueには「data」をセット*/}
      <DataContext.Provider value={[data,setData]}>

        {/*TextContext.Providerを作成、valueには「text」をセット*/}
        <TextContext.Provider value={[text,setText]}>

          <Child/>

        </TextContext.Provider>

      </DataContext.Provider>

    </div>
  )
}

export default App

子要素

src/Child.js
import React from 'react'
import GrandChild from './GrandChild'
 
 const Child = () => {
 
 return(
   <GrandChild/>
 )

}
 
export default Child

孫要素

src/GrandChild.js
import React from 'react'
import GreatGrandChild from './GreatGrandChild'
 
const GrandChild = () =>{
 
  return(
    <GreatGrandChild/>
  )
}

export default GrandChild

曾孫要素

src/GreatGrandChild.js
//useContextをインポート
import React, {useContext} from 'react'
 
//AppコンポーネントからDataContext, TextContextをimport
import {DataContext, TextContext} from './App'
 
 
const GreatGrandChild = () => {
 
  //変数dataにDataContextを代入
  const [data,setData] = useContext(DataContext)
 
  //変数textにTextContextを代入
  const [text,setText] = useContext(TextContext)
 
  return (
    <p>{data.name}{data.age}歳「{text}」</p>
  )
 
}
 
export default GreatGrandChild

Propsを使った値の引き渡し

親→子→孫→曾孫の順にPropsを使って渡していきます(バケツリレー)。

親要素

src\App.js
// ReactからcreateContextとuseStateをimport
import React, {useState} from 'react'

//ContextA.jsのContextコンポーネントをインポート
import Child from './Child'
 
 
function App() {
 
  //dataを作成
  const [data,setData] = useState({
    name: '山田',
    age: '20'
  });
 
 
  //textを作成
  const [text,setText] = useState('こんにちは');
 
  return (
    <div className='App'>
 
      <Child data={data} text={text}/>
 
    </div>
  )
}
 
export default App

子要素

src\Child.js
import React from 'react'
import GrandChild from './GrandChild'

const Child = (props) => {
 
  return(
    <GrandChild data={props.data} text={props.text}/>
  )
 
}
 
export default Child

孫要素

src\GrandChild.js
import React from 'react'
import GreatGrandChild from './GreatGrandChild'
 
const GrandChild = (props) => {
 
  return(
    <GreatGrandChild data={props.data} text={props.text}/>
  )
 
}
 
export default GrandChild

曾孫要素

src\GreatGrandChild.js
import React from 'react'
 
const GreatGrandChild = (props) => {
 
  return (
    <p>{props.data.name}{props.data.age}歳「{props.text}」</p>
 
  )
 
}
 
export default GreatGrandChild
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?