23
4

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 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

ReactでsetStateが即座に反映されない問題を解消する

Posted at

はじめに

普段はBEをメインで開発している筆者がReactのstateの仕様を知らずに2日を溶かしたため

この記事を公開します。

TL;DR

useStateで定義したset関数をコールしても即座にはstateに反映されない。

更新されるタイミングは再レンダリングされたあとに反映される。

set関数をコールした直後にstateを使う場合はuseEffectを使うと値を得られる。

やりたかったこと

タイトルの通りにstateが更新されたら別の関数で新しいstateを用いて処理を行ないたい。

今回はinputに入力されたタイミングでコンソールに出力されるようなプログラムを書いてみます。

NGパターン

set関数をコールした後にstateを直接参照するパターンを考えてみます。

import React, { useState } from 'react'

const Sample: React.FC = () => {
  const [searchText, setSearchText] = useState<string>('')

  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchText(e.target.value)
    console.log(searchText)
  }

  return (
    <div>
      <input
        type="text"
        value={searchText}
        onChange={handleOnChange}
      />
    </div>
  )
}

このように書くと入力した瞬間には「最後に入力された文字が出力されない」という問題があります。

この原因はReactのuseStateで定義したstateはレンダリングされた後に値を更新するという仕様になっています。

では反映されたstateを見るためにはどうしたら良いでしょうか?

Goodパターン

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

const Sample: React.FC = () => {
  const [searchText, setSearchText] = useState<string>('')

  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchText(e.target.value)
  }

  useEffect(() => {
    console.log(searchText)
  }, [searchText])

  return (
    <div>
      <input
        type="text"
        value={searchText}
        onChange={handleOnChange}
      />
    </div>
  )
}

このようにuseEffectの依存配列にstateを指定し、レンダリング後にstateを参照すると更新後の値が得られます。

23
4
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
23
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?