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】「別タブに切り替えて保存」でデータが壊れる?コンポーネント設計で絶対にやってはいけないアンチパターンと対策

1
Posted at

1分でわかる:原因はなに?

複数タブのある編集画面などで、「メインタブで数値を入力した後、別のタブに切り替えてから画面全体の【保存】ボタンを押すと、自動計算が走らずにデータが壊れる」という現象が起きることがあります。

原因は、Reactの超基本特性である「画面に表示されていない(マウントされていない)コンポーネントのプログラムは完全に消滅(アンマウント)する」という挙動を見落としていることです。

自動計算ロジックを「メインタブ(子)」の中に書いてしまうと、別のタブに切り替えた瞬間にそのプログラム自体が消滅するため、計算が動かなくなってしまいます。


視覚的なイメージ

❌ 悪い設計(子コンポーネントにロジックがある)

メイン以外のタブを開いた瞬間、メインタブが消えるため、中の計算ロジックも一緒に消滅します。

[親コンポーネント(保存ボタン)]
       │
       ├── ❌ [メインタブ(計算ロジック)] ── 別のタブを開くと消滅!
       └── ◯ [サブタブ]

⭕ 正しい設計(親コンポーネントにロジックを移動:リフトアップ)

計算ロジックを「親」に持たせることで、どのタブを開いていても常に裏で正しく計算され、安全に保存できます。

[親コンポーネント(計算ロジック & 保存ボタン)] ── 常にここで計算!
       │
       ├── ◯ [メインタブ(入力・表示だけ)]
       └── ◯ [サブタブ]


コードで見る対策

❌ 修正前:子(タブ内部)で計算していた場合

別のタブに切り替えると、この useEffect(計算ロジック)自体が画面から消えて動きません。

// 子(メインタブコンポーネント)の中に書いてしまっていた
useEffect(() => {
  setProfit(sellingPrice - cost); 
}, [sellingPrice, cost]);

⭕ 修正後:親(画面全体)へ引っ越し(リフトアップ)

画面全体を管理する親に移動します。これでタブの切り替えに影響されず、常に最新のデータが計算されます。

// 親コンポーネント(Edit.tsx)へ引っ越し
useEffect(() => {
  setProfit(prices.sellingPrice - prices.cost); 
}, [prices]); // 価格が変わるたびに「常に」親側で自動計算!


まとめ:コンポーネント設計の鉄則

  1. 画面全体の「保存」ボタンが使うデータやロジックは、絶対に「親」に置く(Lifting State Up)
  2. 子コンポーネント(各タブなど)は「入力と表示」だけに専念させる
  3. さらに堅牢にするなら、お金の計算などの重要ロジックはフロント(React)側だけでなく、バックエンド(Laravelなど)側でも行うように設計する
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?