Motomichi Works Blog

モトミチワークスブログです。その日学習したことについて書いている日記みたいなものです。

端末を買い替えたときなどにさくらVPSのサーバーに新しい端末の公開鍵を追加する

参照したページ

はじめに

Macの端末を買い替えたりして、新しい端末の公開鍵を追加したときのメモです。

ログインする方法の選択

以下のいずれかの方法でログインできます。

  1. ssh ログインできる端末のターミナルでログインする。
  2. 「さくらのVPSコントロールパネル」にログインして、「VNCコンソール」を使ってログインする。

上記の「1」の方法で進めます。上記の「2」の方法ではペーストができないので厳しそうです。

ユーザー名については、さくらのVPSの初期設定をしたときに hoge というユーザー名を設定したものとして、以降の説明をします。

ログインする

sshログイン可能な端末でログインします。

.ssh/authorized_keys に一行追加する

エディタでファイルを開きます。

vim ~/.ssh/authorized_keys

以下のような感じで改行して端末ごとの公開鍵を追加して保存します。

ssh-rsa AAAABBB……XXX==

ssh-rsa AAAACCC……XXX==

ssh-rsa AAAADDD……XXX==

おまけ

rootユーザーにスイッチする方法

以下のコマンドでスイッチできます。

$ sudo su -

または

$ sudo su - root

スイッチすると表示が [root@xxx-xxx-xxxxx ~]# になります。

Jestを実行したときに Object.values の記述箇所で TypeError: Cannot convert undefined or null to object at Function.values (<anonymous>) になったので修正する

解決したいこと

HOGE は定数で import しているのに、以下のような感じでテストが失敗しました。
このテストが失敗しているファイルを example.tsx とします。

  ● Test suite failed to run

    TypeError: Cannot convert undefined or null to object
        at Function.values (<anonymous>)

      30 |
      31 |
    > 32 | const hogeFieldOptions = Object.values(HOGE)
         |                                ^

ディレクトリとファイルの構成

問題の example.tsx は以下のようなディレクトリに格納されています。

./
├── const.ts
├── example.tsx
├── index.ts
└── types.ts

index.ts の記述内容

index.ts は他のディレクトリから import しやすいように、以下のようにまとめて export しています。

export * from './const'
export * from './example'
export * from './types'

今回修正できた方法

テストが失敗していた example.tsx は、以下のような感じで index.ts から定数 HOGEtype Foo を import していましたが、

import {
  HOGE,
  type Foo,
} from '.'

以下のように分けたら成功するようになりました。

import {
  HOGE,
} from './const'

import {
  type Foo,
} from './types'

Jestの実行環境が '.' という記述には対応していなかったんでしょうかね...。

Jestを実行したときに Error [ERR_REQUIRE_ESM]: require() of ES Module になったので解決する

参照したページ

Jest の実行環境のサンプル

yarn upgrade について

Error [ERR_REQUIRE_ESM]: require() of ES Module の解消について

Error [ERR_REQUIRE_ESM]: require() of ES Module の調査について

表示されたエラー

以下のようなエラーが表示されました。

Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/your/app/node_modules/string-width/index.js from /path/to/your/app/node_modules/cliui/build/index.cjs not supported.
Instead change the require of index.js in /path/to/your/app/node_modules/cliui/build/index.cjs to a dynamic import() which is available in all CommonJS modules.

翻訳してみると以下の通りでした。

エラー [ERR_REQUIRE_ESM]: /path/to/your/app/node_modules/cliui/build/index.cjs からの ES モジュール /path/to/your/app/node_modules/string-width/index.js の require() はサポートされていません 。
代わりに、/path/to/your/app/node_modules/cliui/build/index.cjs の Index.js の require を、すべての CommonJS モジュールで使用できる動的 import() に変更します。

warning について

yarn install とか実行したときに以下の警告が出ていたっぽい。

warning Pattern ["strip-ansi@^6.0.1"] is trying to unpack in the same destination "/Users/motomichi/Library/Caches/Yarn/v6/npm-strip-ansi-cjs-6.0.1-9e26c63d30f53443e9489495b2105d37b67a85d9-integrity/node_modules/strip-ansi-cjs" as pattern ["strip-ansi-cjs@npm:strip-ansi@^6.0.1"]. This could result in non-deterministic behavior, skipping.
warning Pattern ["string-width@^4.1.0"] is trying to unpack in the same destination "/Users/motomichi/Library/Caches/Yarn/v6/npm-string-width-cjs-4.2.3-269c7117d27b05ad2e536830a8ec895ef9c6d010-integrity/node_modules/string-width-cjs" as pattern ["string-width-cjs@npm:string-width@^4.2.0"]. This could result in non-deterministic behavior, skipping.
warning Pattern ["strip-ansi@^6.0.0"] is trying to unpack in the same destination "/Users/motomichi/Library/Caches/Yarn/v6/npm-strip-ansi-cjs-6.0.1-9e26c63d30f53443e9489495b2105d37b67a85d9-integrity/node_modules/strip-ansi-cjs" as pattern ["strip-ansi-cjs@npm:strip-ansi@^6.0.1"]. This could result in non-deterministic behavior, skipping.

あと has unmet peer dependency も沢山出てる。

エラーを解消する

yarn の cache を削除します。

yarn cache clean

パッケージをアップグレードします。

yarn upgrade

それでも駄目な場合

もしかすると node_modules ディレクトリを丸ごと削除して yarn install し直したら解消されるかもしれません。

yarn の cache を削除します。

yarn cache clean

yarn.lock を削除します。

rm yarn.lock

node_modules ディレクトリを削除します。

rm -rf node_modules

パッケージをインストールし直します。

yarn install

それでも駄目な場合は Jest の実行環境のサンプルを作って挙動を確認する

概要

とにかく簡素なサンプルを作って動かしてみてから、エラーの起こる環境との違いを探ります。

サンプル作成に参照したページ

まずは Jestでテストを書こう | TypeScript入門『サバイバルTypeScript』 を参考に簡素なサンプルを作って、正常にテストが実行できることを確認しました。

プロジェクトを作成する

どこでも良いので任意の場所にサンプルプロジェクトを作成します。

mkdir jest-tutorial
cd jest-tutorial

package.jsonを作成します。

touch package.json

package.json には以下の通り記述します。

{
  "name": "jest-tutorial",
  "license": "UNLICENSED"
}

TypeScriptのインストール

プロジェクトにTypeScriptをインストールします。

yarn add -D typescript

次に、tsconfig.jsonを生成します。

yarn tsc --init

Jestをインストールする

以下のコマンドを実行してインストールします。

yarn add -D jest ts-jest @types/jest

Jestの設定ファイルを作る

次のコマンドを実行すると、Jestの設定ファイル jest.config.js が生成されます。

yarn ts-jest config:init

生成された jest.config.js の内容は次のようになります。

/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};

この @type のコメントはエディターに型情報を与えるためのもので、これを書いておくことで、エディター上で入力補完が効くようになるそうです。

Jestが動くかを確認する

確認用のファイルを作成します。

touch check.test.ts

check.test.ts には以下の通り記述します。Jestが動くかどうかだけ確認したいので、expectなどは記述せずに console.log だけ記述しています。

test("check", () => {
  console.log("OK");
});

以下のコマンドを実行してみます。

yarn jest

成功したらここまではOKです。

JavaScriptの浮動小数の丸め誤差について調べたことの備忘録

参照したページ

はじめに

個人的な備忘録です。

この記事に書いてあることは間違っているかもしれないので、実装はあくまで自己責任でお願いします。

過去に料金計算をJSで行う実装をする機会があって調べました。

10進数の桁数にもよりそうですが、単純な四則演算であれば、小数第何位を四捨五入や切り捨てなどで丸めるかを仕様として定義したうえで big.js を使って計算するのが無難なのかなと思ったので、最終的に big.js を使って実装をしました。

浮動小数点数の演算と丸め誤差についてよくわかっていなかったので 「0.1+0.2≠0.3」を説明できないエンジニアがいるらしい #Python - Qiita を読んでみたところ、10進数から2進数への変換、2進数から10進数への変換、正規化、指数部のバイアスなど、色々丁寧に説明されていて、個人的にはとても良かったです。

浮動小数点数丸め誤差とは

浮動小数点数型と誤差

実数を浮動小数点数すなわち有限桁数の2進数によって計算すると,どうしても誤差が生じる. それを丸め誤差という.

とあります。

10進数の小数の多くは、有限桁の2進数で完全に等しい値を表現することができず、近似値を表現することしかできないため、10進数から2進数、2進数から10進数へ変換するときに誤差が出ます。

浮動小数点数をconsole.log()をするときでも、浮動小数点数を使用した四則演算でも、2進数に変換して演算が行われるため誤差が出ることがあります。

「0.1+0.2≠0.3」を説明できないエンジニアがいるらしい #Python - Qiita で説明されている仮数が53ビット以内に収まらない場合は誤差が出るようです。

IEEE 754 について

wikipedia を参照しました。

IEEE 754 - Wikipedia

1985年にIEEEによって定められた、浮動小数点算術に関する標準規格である。

とあります。

丸め誤差が生じる演算の具体例

その1

小数計算の誤差 | TypeScript入門『サバイバルTypeScript』 を参照しました。

(0.1 + 0.2)Chromeのコンソールに入力すると、以下のスクリーンショットのようになります。

その2

(0.3 - 0.1)Chromeのコンソールに入力すると、以下のスクリーンショットのようになります。

その3

JavaScriptの浮動小数点数型の誤差をなくす | 株式会社CONFRAGE ITソリューション事業部 を参照しました。

(34.3 * 100)Chromeのコンソールに入力すると、以下のスクリーンショットのようになります。

(34.3 * 10 * 10)Chromeのコンソールに入力すると、以下のスクリーンショットのように、意図した結果が得られます。

その4

JavaScriptの浮動小数点数型の誤差をなくす | 株式会社CONFRAGE ITソリューション事業部 を参照しました。

(1051.8 / 10)Chromeのコンソールに入力すると、以下のスクリーンショットのようになります。10で割った場合でもなるんですね。

桁数の多い浮動小数点数と整数をconsole.log()してChromeで確認してみる

以下のような JavaScript のコードを書いて、Chromeの開発者ツールで確認しました。
小数部は19桁に固定したまま、整数部を18桁まで増やしていって、console.log()で出力しました。

const value01 = 2.1234567890123456789;
const value02 = 22.1234567890123456789;
const value03 = 222.1234567890123456789;
const value04 = 2222.1234567890123456789;
const value05 = 22222.1234567890123456789;
const value06 = 222222.1234567890123456789;
const value07 = 2222222.1234567890123456789;
const value08 = 22222222.1234567890123456789;
const value09 = 222222222.1234567890123456789;
const value10 = 2222222222.1234567890123456789;
const value11 = 22222222222.1234567890123456789;
const value12 = 222222222222.1234567890123456789;
const value13 = 2222222222222.1234567890123456789;
const value14 = 22222222222222.1234567890123456789;
const value15 = 222222222222222.1234567890123456789;
const value16 = 2222222222222222.1234567890123456789;
const value17 = 22222222222222222.1234567890123456789;
const value18 = 222222222222222222.1234567890123456789;
const value17int = 22222222222222222;
const value18int = 222222222222222222;

console.log("value01 ", value01.toString());
console.log("value02 ", value02.toString());
console.log("value03 ", value03.toString());
console.log("value04 ", value04.toString());
console.log("value05 ", value05.toString());
console.log("value06 ", value06.toString());
console.log("value07 ", value07.toString());
console.log("value08 ", value08.toString());
console.log("value09 ", value09.toString());
console.log("value10 ", value10.toString());
console.log("value11 ", value11.toString());
console.log("value12 ", value12.toString());
console.log("value13 ", value13.toString());
console.log("value14 ", value14.toString());
console.log("value15 ", value15.toString());
console.log("value16 ", value16.toString());
console.log("value17 ", value17.toString());
console.log("value18 ", value18.toString());
console.log("value17int ", value17int.toString());
console.log("value18int ", value18int.toString());

出力結果は以下のスクリーンショットの通りでした。

  • value17は整数部だけで17桁あり、一の位は4になっています。
  • value18は整数部だけで18桁あり、一の位と十の位が0になっています。
  • value17intやvalue18intも同様の結果が出力されているので、整数でも17桁以上あると正しく変換されないことがわかりますが、16桁の整数が全て正しく変換されることの証明にはなりません。
  • value10の出力を見ると、整数部と小数部を合わせて15桁目までは変数に格納した値がそのまま出力され、16桁目が変化しています。

浮動小数点数型と誤差 の double 型 のセクションを見ると、以下のように記載されています。

double 型の精度(有効桁数)は2進数にして 53 (=52+1) 桁であり,10進数では約 15 桁となる.
指数部も有限であるため, double で表すことのできる実数の絶対値は次のような範囲に限られる.

詳しくは 浮動小数点数型と誤差 をご確認ください。

TypeScript Deep Dive内のbig.js紹介セクション

https://typescript-jp.gitbook.io/deep-dive/recap/number#big.js

財務計算(例:GST計算、セントでのお金、追加など)のために数学を使用する場合は、big.jsのようなライブラリを使用します。
・完全無欠な10進演算
・安全な範囲外の整数値

と紹介されていて、正確な10進数の演算ができそうです。

big.jsのREADME

GitHub - MikeMcl/big.js: A small, fast JavaScript library for arbitrary-precision decimal arithmetic.

big.js, bignumber.js, and decimal.jsの違いについて

big.js の wiki に記載があります。

https://github.com/MikeMcl/big.js/wiki

google翻訳してみると、以下のようなことなどが書かれているようです。ご自身で公式ページをご確認いただくことをお勧めします。

  • big.js は、最小限の任意精度ライブラリです。 これは 3 つの中で最も単純かつ最小で、bignumber.js の半分以下のサイズで、半分のメソッドしかありません。 NaN または Infinity を正当な値として受け入れず、他の基数では機能せず、実行時設定オプションは、小数点以下の桁数と除算を伴う演算の丸めモード、および次の指数値の設定に限定されます。
  • bignumber.js と decmal.js は他の基数の値を処理でき、16 進数の「0x」などの接頭辞をサポート。
  • decmal.js は、C プログラミング言語で見られるような 2 進指数表記で 2 進数、8 進数、および 16 進数の値を処理することもできます。
  • decmal.js はもともと、bignumber.js に非整数累乗のサポートを追加することによって開発されましたが、別のライブラリとしてリリースすることにしました。
  • bignumber.js は、除算を伴う演算が使用されない限り、精度が失われることを心配する必要がない。
  • decmal.js は、非常に小さい値または大きい値をより効率的に処理できるため、より科学的なアプリケーションに適している可能性があります。
  • decmal.js は非整数累乗もサポートし、三角関数と exp、ln、log メソッドを追加します。 これらの追加により、decmal.js は bignumber.js よりも大幅に大きくなります。

10進数と2進数の対応表

10進数 2進数
0.125 0.001
0.25 0.01
0.5 0.1
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000

n進法の位と累乗の関係について

10進法では十の位、百の位、千の位はそれぞれ、10の1乗の位、10の2乗の位、10の3乗の位であることがわかります。
一の位から左へ位が上がるに従って、nの1乗の位、nの2乗の位、nの3乗の位となっています。

また、10進法で小数第一位、小数第二位、小数第三位はそれぞれ、10の-1乗の位、10の-2乗の位、10の-3乗の位であることがわかります。
小数点から右へ小数第一位、小数第二位、小数第三位と右へ行くに従って、nの-1乗の位、nの-2乗の位、nの-3乗の位となっています。

2進法でも同様で、繰り返しの説明となりますが、左へ位が上がるに従って、nの1乗の位、nの2乗の位、nの3乗の位となっています。
小数点から右へ小数第一位、小数第二位、小数第三位と右へ行くに従って、nの-1乗の位、nの-2乗の位、nの-3乗の位となっています。

2進数で表すことができる小数

上記した10進数と2進数の対応表からもわかる通り、2進数では 0.5、0.25、0.125 という風に、2のマイナス累乗の値と、それらを組み合わせた値しか表現できず、どこまでいっても「10進数の0.1と等しい値」が表現できないことがわかります。

10進数の 0.1 は2進数に変換すると循環小数になってしまうことが 「0.1+0.2≠0.3」を説明できないエンジニアがいるらしい #Python - Qiita で説明されています。

コンピュータ内部で使用される2進数の桁は有限であることから、一定の桁数の近似値でしか小数の計算ができず誤差が生まれます。

32ビット単精度の交換形式のビット割り当て

単精度浮動小数点数 - Wikipedia

wikipedia や、色々なところに記載がありますが、32ビット単精度の交換方式

以下のように記載があります。

IEEE 754 での binary32 の定義は次の通りである。

・符号ビット: 1ビット
・指数部の幅: 8ビット
仮数部の幅: 23ビット

  • 符号によって正の数・負の数を表しています。
  • 2進数で演算を行うので、基数は2で固定です。

@ant-design/charts 1.4.2 でチャートを作るオプションのメモ その0001

参照したページ

@ant-design/charts の GitHub リポジトリ

Ant Design Charts 1.x の公式ドキュメント

G2, G6, X6, L7 の公式ドキュメント

G2 v4

G2, G6, X6, L7 の最新バージョンのドキュメント

その他

はじめに

@ant-design/charts を使ってチャートを作る機会があり、使い方がわかりにくかったので自分のために調べたメモです。

AntV ってなに?

AntVシリーズ( https://antv.antgroup.com/ )というものらしく、その中に「G2」「G6」「X6」「L7」や「Ant Design Charts」が含まれるらしいです。

この記事を書くにあたって使用しているパッケージのバージョン

  • react: 18.2.0
  • @ant-design/charts: 1.4.2
  • @ant-design/pro-components 2.4.4
  • antd: 5.4.4

@ant-design/charts の README を読む

まず GitHub - ant-design/ant-design-charts: A React Chart Library のページを見ると、React用のチャートライブラリで G2, G6, X6, L7 というものがベースになっているらしいです。

README にはとても簡素な折れ線グラフのサンプルコードが載っています。

ベースになっているという G2 のリポジトリからリンクされている Gallery | G2 を見ると、Ant Design Charts が G2 をベースとして使用していることがわかりますし、各種Chartだけでなく、Charts の公式ドキュメントの設定例には無い Label, Tooltip, Legend などの設定例もあり、参考になりそうです。

また Gallery | G2 に掲載されている v4 の例では、以下のスクリーンショットのように、左下の領域にはコードが表示され、右カラムにはAPIドキュメントが表示されて、とても見やすい構造になっています。
ただ中国語でしか表示されないので、翻訳しないと私は読めませんが。

ColumnChart を作ってみる

折れ線グラフは README に例があるので、棒グラフを作ってみます。

公式ドキュメントの https://ant-design-charts.antgroup.com/examples のページに例が沢山あるので、Grouped column plot( https://ant-design-charts.antgroup.com/en/examples/column/grouped#basic )の例からコピペしたコードをちょっと編集して、以下のコンポーネントを作成しました。

とにかく公式ドキュメントの例をコピペすればざっくりとチャートを作成するところまではできます。

個人的には「@ant-design/plots から import するの?」っていうのが、当初どこのドキュメント見れば良いのかわからなくさせた要素のひとつでした...。
GitHub の README に載っている LineChart の例は @ant-design/charts から import しているんですよね...。

demoColumn.tsx は以下の通りです。

import * as React from 'react'
import { Column, ColumnConfig } from '@ant-design/plots'

export const DemoColumn = () => {
  const data = [
    {
      name: 'group1',
      period: '2023-12-01',
      time: 20,
    },
    {
      name: 'group1',
      period: '2023-12-02',
      time: 40,
    },
    {
      name: 'group1',
      period: '2023-12-03',
      time: 29,
    },
    {
      name: 'group2',
      period: '2023-12-01',
      time: 12,
    },
    {
      name: 'group2',
      period: '2023-12-02',
      time: 23,
    },
    {
      name: 'group2',
      period: '2023-12-03',
      time: 35,
    },
  ];

  const config: ColumnConfig = {
    data,
    isGroup: true,
    seriesField: 'name',
    xField: 'period',
    yField: 'time',
  };

  return <Column {...config} />;
};

上記したコンポーネントは、以下のスクリーンショットのように表示されました。凡例( legend )も表示されました。

チャートの描画に使用する data は任意の型のオブジェクトの配列です。

今回の例では以下の型の配列です。

{
    name: string;
    period: string;
    time: number;
}[]

config のプロパティを読んでおく

概要

上記した例のプロパティを読んで理解していきます。

isGroup

isGroup: true を設定することで、スクリーンショットにあるように、青と緑の棒グラフが横に並んで描画されます。

設定しない場合は青と緑の棒グラフが重なって描画されます。

xField

xField: 'period' を設定することで、data の配列要素の、どのプロパティをx軸方向のラベルとして使用するかを設定しています。

yField

yField: 'time' を設定することで、data の配列要素の、どのプロパティをy軸方向の値として使用するかを設定しています。

seriesField

seriesField: 'name' は data の配列要素の、どのプロパティを使ってデータをグルーピングするかを設定しています。

今回の場合、 data[number].name の値である group1, group2 がそれぞれグループ名として使用され、凡例の表示などに使用されています。

グルーピングされることによって、以下のことができるようになります。

  • 凡例が表示されるようになる
  • isGroup: true の設定が効いて棒グラフが横並びにできる

型からその他のプロパティを確認する

node_modules/@antv/g2plot/lib/plots/column/types.d.ts など、型ファイルを見るのも参考になると思います。

また、例えば DualAxes の legend にどのようなプロパティを設定できるのか調べたい場合は、以下の例のようにコードを書いてみると候補が出てくるので、そういった方法も便利です。

import { DualAxes, type DualAxesConfig } from '@ant-design/plots'

type Hoge = Exclude<Exclude<DualAxesConfig['legend'], undefined>, false>

一応詳細な手順を書いておくと以下の通りです。

  1. type DualAxesConfig を import する。
  2. type Hoge = Exclude<Exclude<DualAxesConfig['legend'], undefined>, false> まで書く。
  3. 手順の「2」のコードに続いて [''] を入力すると、以下のスクリーンショットのように候補が出てくる。

チャートの config のプロパティを追加して試していく

概要

棒グラフや折れ線グラフなど、基本的なチャートの設定項目を知るには、Ant Design Chart の公式ドキュメント https://ant-design-charts.antgroup.com/ と G2の公式ドキュメント 图表 - Chart | G2 を合わせて見ていくのがよさそうです。

中国語のページをまるごと Chrome などの翻訳機能で日本語にしてみたり、ヘッダーにあるメニューから英語に切り替えたりすると多少は読みやすいかもしれません。

気になったところや、適当に目についたところから調べて、以下にプロパティの設定例を記載していこうと思います。

度量 - Scale ( y軸方向の目盛りの最小値と最大値 )

G2 のドキュメントでいうと 度量 - Scale | G2 の設定項目です。

y軸方向の目盛りの最小値と最大値の設定です。

どうやら Ant Design Charts の ColumnConfig型 には scale というプロパティは無さそうで、以下のように yAxis に設定するようです。

  const config: ColumnConfig = {
    data,
    isGroup: true,
    seriesField: 'name',
    yAxis: {
      max: 100,
      min: 0,
    },
    xField: 'period',
    yField: 'time',
  };

以下のスクリーンショットのように、y軸の目盛りが0〜100になりました。

設定例

legend

    legend: {
      itemName: {
        // 凡例の色や文字サイズなど
        style: {
          fill: '#FF0000',
          fontSize: 12,
        },
      },
      marker: {
        symbol: 'circle',
      },
      position: 'bottom',
      // selected のプロパティは上記した ColumnChart の例に合わせて group1, group2 としていますが、凡例として表示される文字列をプロパティ名として使います。
      selected: {
        group1: true,
        group2: false,
      },
      title: {
        style: {
          stroke: '#00FF00',
        },
      },
    },

yAxis

    yAxis: {
      max: 100,
      min: 0,
      tickLine: {
        style: {
          stroke: '#FF0000',
          lineDash: [2, 2],
        },
      },
      subTickLine: {
        style: {
          stroke: '#FF0000',
          lineDash: [2, 2],
        },
      },
    },

Object.keys()の返り値をstring[]型でなくユニオン型の配列にしたい

参照したページ

関数を定義して解決する

以下のようにするとkeysは ("hoge" | "foo" | "baz")[] 型になります。

  const obj = {
    hoge: 'value',
    foo: 'value',
    baz: 'value',
  };

  function getKeys<T extends Record<string, unknown>>(obj: T): (keyof T)[] {
    return Object.keys(obj)
  }

  const keys = getKeys(obj);

useEffectが依存しているstateの前回の値を取得する

参照したページ

サンプルコード

  const [hoge, setHoge] = React.useState('');
  const [prevHoge, setPrevHoge] = React.useState('');

  React.useEffect(() => {
    return () => {
      setPrevHoge(hoge)
    }
  }, [hoge]);