Reactのkeyを使って、意図的な再レンダーを走らせる

「え？keyって無駄なレンダリングが走らない様にするためのものでしょ？」

その通りなのですが、今回は逆に利用する方法を紹介します。

## 仕組み
- keyは異なるレンダー間でどの子要素が変化しない可能性があるのかについてヒントを出すことができるものである [公式](https://ja.reactjs.org/docs/reconciliation.html)
- 逆に、keyが違う（変わった）のであれば、それは別物として扱われる

## 利用例1、defaultValueの変更
defaultValueは、[非制御コンポーネント](https://ja.reactjs.org/docs/uncontrolled-components.html)の場合に用いる初回のみ設定可能な入力値です。
初回のみなので後から変更することができないのですが、これを変更したいケースがあります。例えばdefaultValueにAPIから取得した値を入れたい場合、具体的には編集フォームで編集元データをfetchしてくるけれど、その前からスケルトンとして入力フォームは見せておきたい場合です。

まずは動かないコードです。
前述の通り、defaultValueは初回のみしか設定できないので、最初に渡された "empty..." のまま変化しません。
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="putan" data-slug-hash="JjKgzXz" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="no_key_defaultValue">
  <span>See the Pen <a href="https://codepen.io/putan/pen/JjKgzXz">
  no_key_defaultValue</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

そこでfetchしたデータを含めた値をkeyに指定します。
これにより`InpurFrom`は別物になったと判断して再レンダーされ、defaultValueも再度読み込ませることができるのです。

```diff
- <InputForm defaultValue={val} />
+ <InputForm defaultValue={val} key={`input_${val}`} />
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="putan" data-slug-hash="PozMLep" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="with_key_defaultValue">
  <span>See the Pen <a href="https://codepen.io/putan/pen/PozMLep">
  with_key_defaultValue</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>


## 利用例2、汎用的なリストの切替
非制御だけでなく、制御コンポーネントでも利用ケースが考えられます。
セレクトボックスやラジオボタン、チェックボックスなどのリスト系フォームでリストを切り替えたいケースです。
サンプルとして二段に分かれたラジオボタンを用意しました。

まずは動かないパターンです。
1段階目のメインメニューを`パン`に変更してサブメニューが切り替わっても、サブメニューのstateには`ごはん`の時の値が保持されているためサブメニューが未選択状態になってしまいます。
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="putan" data-slug-hash="JjKgqXM" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="no_key_radio">
  <span>See the Pen <a href="https://codepen.io/putan/pen/JjKgqXM">
  no_key_radio</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

そこでサブメニューの`RadioGroup`にkeyにメインメニューの`RadioGroup`の値をkeyとして渡します。
これにより、メインメニューの変更するとサブメニューの`RadioGroup`も別物として判断され、local stateも初期化されます。

```diff
  <RadioGroup
+   key={mainMenu}
    name="subMenu"
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="putan" data-slug-hash="vYKoMNm" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="with_key_radio">
  <span>See the Pen <a href="https://codepen.io/putan/pen/vYKoMNm">
  with_key_radio</a> by ぷーたんは社会人リハビリ中 (<a href="https://codepen.io/putan">@putan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## まとめ
- keyを利用してdefaultValueやsetStateの初期値などをリセットする方法を紹介
- うまく使うことでuseEffectなどを用いた複雑な処理を書かなくても意図した制御が可能になる