ログオフ
開発2026-06-06

React Native で kg/lbs の単位変換が二重にかかるバグと設計のポイント

単位を切り替えたら数値がおかしくなった。DB 保存時にも変換、表示時にも変換で二重変換になっていた。DB は常に単一単位で保存し、表示時だけ変換するのが正解。

React Native で kg/lbs の単位切り替えを実装したら、表示される重量が膨らんでいった。原因は変換が二か所で走っていたこと。保存時に一回、表示時にもう一回。教訓は単純で、DB は単一単位で持ち、変換は表示の瞬間だけにする。

事象

前提を固定しておく。アプリの単位設定は「lbs」、入力欄には「100」(=100kg 相当のつもりで入力)。期待する表示は 220.46 lbs。ところが画面には 486 と出た。

  • 入力した値より表示が大きく膨らむ(100 → 486)
  • 単位の切り替えを繰り返すと、そのたびにさらに膨らむ
  • 元の単位に戻しても正しい値に戻らない(DB の中身が既に汚れているため)

486 という数字は偶然ではない。100 に変換係数 2.20462 を二回掛けると 100 × 2.20462² ≈ 486 になる。係数が二重に乗っている、という当たりがここで付く。

原因

保存時にも表示時にも変換を入れていた。どちらか片方だけのつもりが、両方で走っていた。

// ❌ 二重変換パターン

// 保存時:lbs 設定だからと kg→lbs に変換してから保存してしまう
const valueToSave = unit === 'lbs' ? kgInput * 2.20462 : kgInput;
db.save({ weight: valueToSave }); // ← ここで単位がブレる(lbs で入る行と kg で入る行が混在)

// 表示時:DB の値を「kg が入っている」前提でさらに lbs へ変換
const display = unit === 'lbs' ? saved * 2.20462 : saved;

設定が lbs のまま 100 を保存して表示するまでを追う。

  1. 保存:100 × 2.20462 = 220.46 を DB に書く
  2. 表示:DB 値を kg とみなして 220.46 × 2.20462 ≈ 486 に変換
  3. 画面に 486 が出る

根っこは数式ではなく**「DB に入っている値がどの単位なのかが決まっていない」こと**だ。保存層は「設定単位で入れる」と思い、表示層は「kg が入っている」と思っている。前提がずれた二つの層が、それぞれ良かれと思って変換する。だから切り替えるたびに係数が積み上がる。

解決策

DB は常に kg で持つ。入力は受け取った瞬間に kg へ正規化し、変換は表示の一回だけにする。

// ✅ DB は kg で統一。境界(入力・表示)でだけ変換する

// 保存時:lbs で入力されたら即 kg へ戻してから保存
const valueToSave = unit === 'lbs' ? lbsInput / 2.20462 : kgInput;
db.save({ weight: valueToSave }); // 行の単位は常に kg で確定

// 表示時:DB の kg をその場の設定単位へ
const display = unit === 'lbs' ? dbWeight * 2.20462 : dbWeight;

ポイントは「DB の値が何の単位か」を一意に決めること。kg に固定すれば、設定をどう切り替えても DB は不変で、変わるのは表示だけになる。変換が境界(入力と表示)にしか存在しなくなるので、二重に掛かりようがない。

補足

  • 入力と表示が単位変換の境界。DB はその内側で常に一単位、と決めておくと迷わない。cm/inch、km/mile、℃/℉ でも同じ
  • 変換係数は定数に切り出して両方向(kg↔lbs)で同じ値を使う。掛け算と割り算で別々の近似値を書くと、往復で誤差が残る
  • 既に二重変換で汚れた行があるなら、マイグレーションで weight / 2.20462 を当てて正規化する。ただし「どの行が二重変換済みか」を区別できないと一律補正もできない。だからこそ保存単位を最初から固定しておく価値がある

関連記事

開発 一覧へ