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?

【React】useStateの数値に制限をつける方法

Posted at

概要

Stateの数値に上限や下限など、制限をつける方法についてです。
クラスだったらコンストラクタ内、setter内で制限をかけたりできるのですが、Stateでも同じようなことができないかと思い、調べ、その方法をまとめました。

ざっくり説明すると、カスタムフックを作成、その中でset関数をラップした関数を作成、そこで値をいじることでうまくできます。
(カスタムフック使わなくとも、そのままラップ関数を作ってできはしますが、set関数が直接使われないように自作フックを使った方が良さそうです)

コード例

以下の例では、カラーコード(RGB値)を State として持たせています。
RGBが取りうる値は 0 ~ 255 なので、それ以外の数値にならないように制限をかけています。
(細かいところはコード内で説明を記載しています)

  • useRGB.jsx
import { useState } from "react";

// RGB型
type ColorRGB = {
  red: number;
  green: number;
  blue: number;
};

// 初期化用定数
const INITIAL = {
  red: 0,
  green: 0,
  blue: 0,
} as const satisfies ColorRGB;

export default function useRGB() {
  const [colorRGB, set] = useState<ColorRGB>(INITIAL);

  /**
   * RGB数値の範囲外にいかないように制限する処理(制限用関数)
   */
  function clamp(colorNum: number): number {
    // 0より小さいなら0に変換し、255より大きいなら255に変換する
    return Math.max(0, Math.min(255, colorNum));
  }

  /**
   * RGBの値を変更する処理
   * (ここで更新時に制限用関数を使って数値に制限をかける)
   */
  function setColorRGB(colorRGBValue: ColorRGB) {
    set({
      red: clamp(colorRGBValue.red),
      green: clamp(colorRGBValue.green),
      blue: clamp(colorRGBValue.blue),
    });
  }

  return { colorRGB, setColorRGB };
}
  • Color.tsx
import { useMemo } from "react";
import useRGB from "@/hooks/useRGB";

export default function Tmp() {
  // 自作フック
  const { colorRGB, setColorRGB } = useRGB();

  /**
   * ボタンクリック時処理
   */
  function handleClick() {
    // クリックする度+30される
    // ただし制限により、255以上にはならない
    const newRGB = {
      red: colorRGB.red + 30,
      green: colorRGB.green + 30,
      blue: colorRGB.blue + 30,
    };
    setColorRGB(newRGB);
  }

  /**
   * カラーコードの RGB → 16進数 変換(見た目で分かりやすくする用)
   */
  const colorHex: string = useMemo(() => {
    // 各値を16進数に変換し、2桁になるように0埋めする
    const { red, green, blue } = colorRGB;
    const toHex = (value: number) => {
      return value.toString(16).padStart(2, "0");
    };
    return `#${toHex(red)}${toHex(green)}${toHex(blue)}`.toUpperCase();
  }, [colorRGB]);

  return (
    <div
      style={{
        margin: 8,
      }}
    >
      {/* クリックする度に白くなるボタン */}
      <button
        onClick={handleClick}
        style={{
          backgroundColor: colorHex,
          width: 100,
          height: 100,
          border: "2px solid #111",
          borderRadius: 8,
        }}
      ></button>
      <p>{`Red:${colorRGB.red}`}</p>
      <p>{`Green:${colorRGB.green}`}</p>
      <p>{`Blue:${colorRGB.blue}`}</p>
    </div>
  );
}
  • 動作

See the Pen useRGB by asa (@asa0903) on CodePen.

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?