1
0

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.

[自分用]Next.jsのState

Last updated at Posted at 2023-05-19

とりあえずやってみよう!

とりあえずクリックしたらfooが1ずつ増える関数を書いてみる。

export default function Home() {
  let foo = 1;

  const handleClick = () => {
    foo = foo + 1;
    console.log(foo);
  };

  return (
    <>
      <h1>{foo}</h1>
      <button
        onClick={handleClick}>
        ボタン
      </button>
    </>
  )
}

しかしこのコードだけではブラウザの数字がずっと「1」のままになってしまう。
コンソールはしっかりと1ずつ増えているのに、、、

その原因は再レンダリング!!!
Reactにおいて画面の表示を変えるには「再レンダリング」がされなくてはならない。
しかしそれにはいくつか条件がある。
①ページ遷移したとき
②データの変更(カウンターのように、単にクライアントサイドだけで変更されたときはダメ)
③コンテキストの変更
④getStaticPropsまたはgetServerSidePropsの呼び出し
など。

条件に当てはまればブラウザの数字も変わる!

もっと詳しくいうと

ボタンを何回もクリックするとfoo値はもちろん変わっている
しかしReactは変数の変化だけだと、変わったことを認識しない!
そのためHomeコンポーネントが2回目以降のレンダリングがされないので、一番初めの「1」になったままということ。

「Homeコンポーネントがもう一回呼び出される = 再レンダリング」ということなので、再レンダリングがされる条件に当てはめなければならない。

ここで登場 useState!

import { useState } from 'react';

export default function Home() {
  const [foo, setFoo] = useState(1);

  const handleClick = () => {
    setFoo(foo => foo + 1);
  };

  return (
    <>
      <h1>{foo}</h1>
      <button
        onClick={handleClick}>
        ボタン
      </button>
    </>
  )
}

まず[foo, setFoo] = useState(1)について解説。
言葉にすると次のようになる。[状態を持った変数, 関数] = useState(初期値)
fooが状態を持った変数なので、fooが変わったら再レンダリングされる。←ここ大事だよ!

よって初期値を0にすると状態が変更されないので、console.logは一度しか表示されない。
つまり再レンダリングされていないのだ。

export default function Home() {
  const [foo, setFoo] = useState(1);

  const handleClick = () => {
    //初期値に注目!
    setFoo(foo => foo + 0);
  };

  //ここに注目!これはHomeコンポーネントが呼び出されないと実行されないよ!
  //だから再レンダリングされないと「ボタン」をいくら押しても一度しか表示されないよ!
  console.log(foo);

  return (
    <>
      <h1>{foo}</h1>
      <button
        onClick={handleClick}>
        ボタン
      </button>
    </>
  )
}

※ちなみに、
foo + 1ではなくfoo => foo + 1の理由は、引数fooを用意することにより、
前回の状態をしっかり反映させることができるため
仮に2ずつ増やしたくてfoo + 1を2行書いても、fooに入る数値は一緒なので1ずつしか増やせない。

分割配列について

[foo, setFoo]の部分は分割配列。

useState()には2つの返り値が存在しているため、
通常であれば返り値を別の変数に入れて変数[0]変数[1]と指定して取り出す。
それがめんどくさいので[foo, setFoo]を用意してそれぞれに突っ込んじゃおうという策略。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?