LoginSignup
17
11

More than 5 years have passed since last update.

運用中のアプリケーションにReact Hooksを入れてみて気付いたこと

Posted at

前回の記事では、「運用中アプリケーションのReactのバージョンを試しに最新にした時の、npmライブラリ変更とその解決法メモ」を投稿しました。折角Reactのバージョンを最新にしたので、React Hooksを導入してみました!
React Hooksについては初心者なので悪しからず…👀

導入

useState

functionコンポーネントがローカルステートを使えるようになりました。ローカルステートの初期値の設定や、setState等が出来ます。
まず、今までReactをimportしていたところを、下のようにuseStateを使えるようにしてあげます。

import React, { useState } from 'react'

まずはclassで作っていたコンポーネントをFCに変えちゃいます。

以前までのコード

class Component extends React.Component {
  ...
}

変更後のコード

const Component = () => {
  ...
}

ローカルステートは下のように記述していたのを、useStateを使って変更しました。

/* 変更前 */
state = {
  UserSelf: {}
}

/* 変更後 */
const [UserSelf, setUserSelf] = useState({})

UserSelfがステート名、setUserSelfsetStateみたいなもので、UserSelfを変更したい場合に用います。
useStateの引数の中には、初期値を入れてあげます。これで準備は完了です!

今までthis.state.UserSelfthis.setState({ UserSelf: { id: 1 } })とか書いていたところを、下のように書き替えてあげます。

return (
  <div>
    /* 以前までのコード */
    {this.state.UserSelf}
    /* 変更後 */
    {UserSelf}
  </div>
)
/* 以前までのコード */
this.setState({ UserSelf: { id: 1 } })
/* 変更後 */
setUserSelf({ id: 1 })

useEffect

componentDidMount()などライフサイクルメソッドを使用しているので、こちらも新しいuseEffectに書き換えていきます!
useEffectはライフサイクルメソッドに代わるものです。componentDidMount()componentDidUpdate()componentWillUnmount()を組み合わせたものというイメージです。

前準備として、useEffectを使えるようにしておきます。

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

componentDidMount()内の記述を一旦関数に書き換えてuseEffect内で呼び出す事にしました。

以前までのコード

class Component extends React.Component {
  ...
  async componentDidMount() {
    const response = await axios.get(`https://samplejson.com/${this.props.resource}`)
    this.setState({ resource: response.data })
  }
  ...
}


変更後のコード
fetchResource()という名前の関数で作成しました。

const Component = (props) => {
  ...
  const fetchResource = async () => {
    const response = await axios.get(`https://samplejson.com/${props.resource}`)
    this.setState({ resource: response.data })
  }
  ...
}

fetchResource()useEffectの中で呼び出してみます!

const Component = props => {
  ...
  const fetchUser = async props => {
    setUser(foo)
    setLoading(false)
  }

  useEffect(() => {
    fetchUser(props)
  }, [props])
  ...
}

こちらの記述では上手くいきませんでした。
(動画の英語が分からなかった訳ですが笑、)上手くいかなかったのは、useEffectの非同期処理が何度も繰り返し呼ばれているようです。
これにはuseEffectの第二引数が関係してくるようです。こちらの記事を参考に勉強させていただきました!
useEffectフックのしくみ

第二引数を指定しない場合

ノンストップでAPIが呼び出され、毎度リレンダーされる。

useEffect(() => {})

第二引数に空の配列を指定した場合

初期レンダリングだけ実行される。(componentDidMount()

useEffect(() => {},[])

参考にさせて頂いた記事では、「空配列を渡すとバグの原因になる。依存関係が不足しているとuseEffectが更新された時予期せぬ挙動の原因となるでしょう」とありました。注意が必要そうです…!

第二引数に値を指定した場合

引数に渡した値が更新されるたびに、useEffect()が呼ばれその度にレンダーしてくれる。

useEffect(() => {},[value])

なるほどと動画を見ながら第二引数にローカルステートを色々入れて試したのですが、何度もレンダーされまくってしまいました…!😭 解決法は上記で紹介させ頂いたuseEffectフックのしくみの「useEffectでデータを取得する」の章がすっごく分かり易かったです!こちらを参考に修正しました。

useEffect(() => {
  fetchUser(props)
}, [setUser])

今回は、第引数に セッター関数 を渡してあげるのが正解のようでした…!(ずっとステート名入れてた〜😭💦)
これで何度もレンダーされるのは解消されました。🎉

関数を使い回せるように

const [UserSelf, setUserSelf] = useState({})useEffect(() => {})をまとめて、別ファイルにすれば、使い回しが出来ます!👀
Udemyでは、別ファイルの関数をuseResources()とし、非同期のエンドポイントを引数に渡してあげるようにすればどのコンポーネントでも使えると紹介していました。

// ユーザー一覧コンポーネント
import useResources from './useResources';

const UserList = () => {
  const users = useResources('users')

  return (
    ...
  )
}

// 記事一覧コンポーネント
import useResources from './useResources';

const ResourceList = () => {
  const users = useResources('resource')

  return (
    ...
  )
}

終わりに

16.6で追加されたlazy&Suspenseも試したい…!
React 16.6で追加されたReact.Suspenseについて
(超便利っ!!)バージョンアップと共に便利になっていくReactに感動しているのと同時に、英語に怖じ気ずかないようにしようと思いました〜

また、今回もUdemyを参考に勉強しました。Modern React with Redux -2019 Update
(恥ずかしい話、英語が聞き取れず第二引数のくだりがほとんど分かりませんでした😭ですが日本語記事でも理解を深めることが出来ましたので、大助かりでございました…っ!)

React公式ドキュメントでも「フックの導入」が公開されていました。React界隈の著名人もReact Hooksについてブログ記事で使い方のレクチャーをしています!

また…、
この記事もあっさり&ざっくり、パラパラしすぎていると自負しているので笑、文章の書き方についても勉強します😅

17
11
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
17
11