LoginSignup
46
37

More than 5 years have passed since last update.

【React】ざっくり入門(Hooks)

Last updated at Posted at 2019-03-05

概要

React16.8から新しい機能としてHooksが導入されました。
以下の順序でHooksとは何かざっくり入門していきましょう。

Hooksとは?

Hooksとは従来classコンポーネントでしか使用できなかったstate等の機能をfunctionalコンポーネント(関数コンポーネント)でも使用可能にする機能です。

この記事では以下の3種類のhookを紹介します。

  • (1)State Hook:statesetStateを関数コンポーネント内で使用可能にする。
  • (2)Effect Hook:データ取得やDOM変更といったside effectsを関数コンポーネント内で使用可能にする。
  • (3)Custom Hooks:共通のロジックをコンポーネント間での再利用を可能にする。

Hooksの規則

Hooksを使用する際には以下の規則を守りましょう。

  • (1) Hooksは必ずコンポーネント中の一番上(トップレベル)に定義する。
  • ループ、条件分岐、ネストされた関数の中で定義してはいけません。)
  • (2) HooksはReactの関数コンポーネントの中だけで呼ぶ。(通常のJavascriptの関数から使用してはいけません。)

State Hook

useStateと呼ばれるhookを使用する事でstatesetStateを関数コンポーネント内で行える様にします。
classコンポーネントuseStateを使用した関数コンポーネントを比較して使用方法を確認して見ましょう。

従来のclassコンポーネント

以下の例では主に2つの事を行なっています。

  • (1)stateで初期値に0を持つcountを定義する。
  • (2)setStateでボタンを押すたびにcount1を足している。

output2

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>{this.state.count} 回クリックしました。</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          クリックしてください。
        </button>
      </div>
    );
  }
}

StateHook

上記と全く同じ事をuseStateを使用して行います。
基本的な使用方法(定義方法)は以下の通りです。

const [state, setState] = useState(initialState);

useStateでは従来のstatesetStateを同時に設定しする様なイメージです。
上記のcountやそのsetStateuseStateを使用して定義すると以下の様になります。

import React, { useState } from  'react';

function Counter() {
  const [count, setCount] = useState(0)
}

以下の3点に注目して上のコードを見てみましょう。

  • (1) countがclassコンポーネントでいうthis.state={count:0}の部分。
  • (2) setCountがclassコンポーネントでいうsetStateの部分。
  • (3) useState()に渡されている0countの初期値。

また以下の2点を踏まえて残りのコードを完成させます。

  • (1) stateを直接参照できる。
  • (2) setCountを使用してstateを更新できる。
import React, { useState } from  'react';

function Counter() {
  const [count, setCount] = useState(0)

  return(
    <div>
      // (1) stateを直接参照できる。
      <p>{count} 回クリックしました</p>

      // (2) setCountを使用してstateを更新できる。
      <button onClick={() => setCount(count + 1)}> クリックしてください。</button> 
    </div>
  )
}

export default Counter;

ちなみに以下の様にして複数のstateを定義していきます。

import React, { useState } from  'react';

function Counter() {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('')

  return(
    <div>
      <p>{count} 回クリックしました</p>
      <button onClick={() => setCount(count + 1)}> クリックしてください。</button>
      <p>私の名前は{name}</p>
      <button onClick={() => setName('テスト太郎')}>名前表示</button>
    </div>
  )
}

export default Counter;

Effect Hook

従来のclassコンポーネントではcomponentDidMountcomponentDidUpdatecomponentWillUnmount等の中でデータ取得やDOM変更を行なっていましたが、これをuseEffectと呼ばれるhookを使用し、関数コンポーネントでも使用可能にします。

こちらもuseEffectの使用方法を従来のclassコンポーネントと比較して確認していきます。

従来のclassコンポーネント

従来はcomponentDidMountはマウントされた直後に1回だけ呼ばれ、componentDidUpdateはコンポーネントが更新された後に呼ばれ、ここでデータの取得等を行いました。

output3

import React from  'react';

class Effect extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    console.log('マウントされました。')
  }

  componentDidUpdate() {
    console.log('アップデートされました。')
  }

  render() {
    return (
      <div>
        <h1>{this.state.count} 回クリックしました。</h1>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          クリックしてください。
        </button>
      </div>
    );
  }
}

EffectHook

useEffectは従来のcomponentDidMountcomponentDidUpdatecomponentWillUnmountの3つを組み合わせた様なもので、基本的にrenderされる毎に呼ばれます。(first renderを含む。)
hooksを使用した開発ではここでside effectsを実行します。

output4

import React, { useState, useEffect } from 'react'

function Effect() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    console.log('レンダーされました。')
  })

  return(
    <div>
      <h1>{count} 回クリックしました</h1>
      <button onClick={() => setCount(count + 1)}> クリックしてください。</button>
    </div>
  );
}

Custom Hooks

上記で記載した通り、共通のロジックをコンポーネント間での再利用を可能にします。

以下の2つのコンポーネントがあるとします。

  • (1) 受け取ったid1だったらログイン中ですを返す、status.js
  • (2) 受け取ったid1だったらおかえりなさいを返すmessage.js
status.js
export default function Status(props){
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const handleStateChange = (id) => {
    if(id === 1){
      setIsLoggedIn(true)
    }
    else{
      setIsLoggedIn(false)
    }
  }

  useEffect(() => {
    handleStateChange(props.user.id)
  })

 const status = isLoggedIn ? 'ログイン中' : 'サインアップ'

  return (
    <>
      <h1>Status: {status}</h1>
    </>
  )
}
message.js
export default function Message(props){
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const handleStateChange = (id) => {
    if(id === 1){
      setIsLoggedIn(true)
    }
    else{
      setIsLoggedIn(false)
    }
  }

  useEffect(() => {
    handleStateChange(props.user.id)
  })

 const message = isLoggedIn ? 'おかえりなさい' : 'あなたは誰ですか?'

  return (
    <>
      <h1>Message: {message}</h1>
    </>
  )
}

ここの共通したロジック部分をcustom Hookを使用する事で、以下の様に抜き出す事ができます。
抜き出したロジックのコンポーネントはuseから始まる慣習があります。今回はuseLoginと名付けました。

useLogin
import { useState, useEffect } from 'react';

export default function useLogin(userId){
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  // コンポーネント間で再利用したいロジック
  const handleStateChange = (id) => {
    if(id === 1){
      setIsLoggedIn(true)
    }
    else{
      setIsLoggedIn(false)
    }
  }

  // side effectsを実行する。
  useEffect(() => {
    handleStateChange(userId)
  })

  return isLoggedIn;
}

useLoginを使用する事でstatus.jsmessage.jsをよりスッキリ書くことができます。

user.js
import React from 'react';
import useLogin from './useLogin';

export default function Status(props){
  const status = useLogin(props.user.id) ? 'ログイン中' : 'サインアップ'
  return (
    <>
      <h1>Status: {status}</h1>
    </>
  )
}
message.js
import React from 'react';
import useLogin from './useLogin';

export default function Message(props){
  const message = useLogin(props.user.id) ? 'おかえりなさい' : 'サインアップしてください'
  return (
    <>
      <h1>Message: {message}</h1>
    </>
  )
}

custom hooksでは他にも色々な事ができるので、詳細は公式ドキュメントで確認ください。

参照

hooksの説明としては本当にざっくりでしたので、詳細は公式ドキュメントで確認ください。

46
37
2

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
46
37