reactjs / reactjs/react.dev

Highlight Possible Necessity of keys for Conditional Rendering

オープン
#1,779 コメント 0 件 リアクション 5 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
JavaScript
スター
11.8k
フォーク
7.9k
平均マージ
1日 11時間
マージ済み PR(30日)
11

説明

Motivation

Keys may be necessary outside the context of any "list" or array, especially when using conditional rendering. This isn't emphasized enough in the docs, and examples (therein and elsewhere) tend to lead to a false association between keys as having directly to do with map(), <li> elements, or JavaScript arrays. As I understand it, at its root, keys have to do with children, and type correspondence based on position during reconciliation.

Related issues such as https://github.com/reactjs/reactjs.org/issues/79 don't seem to directly address this.

Personal Experience

Most recommendations I find online seem to boil down to "use keys when using map()"(or <li> or arrays). It's rare to find a discussion related to conditional rendering and most people tend to be unaware of it.

I've been in a project wherein conditional rendering was heavily used, which led to a hard to find bug due to the absence of keys.

Code snippet in render()

return (
            <div>
               { this.state.showCounter2 ? 
               (
                <React.Fragment>  
                    <CounterWithLifeCycleLog name={'myCounter1'} 
                    counter={0} />
                    <CounterWithLifeCycleLog name={'myCounter2'} 
                    counter={this.state.counter2} />
                    <CounterWithLifeCycleLog name={'myCounter3'} 
                    counter={0} />
                </React.Fragment>

               ) : (
                <React.Fragment>
                    <CounterWithLifeCycleLog name={'myCounter1'} 
                    counter={0} />  
                    <CounterWithLifeCycleLog name={'myCounter3'} 
                    counter={0} />    
                </React.Fragment>

               )

The above code has a bug. When this.state.showCounter2 moves from true to false myCounter3 will be unmounted instead of myCounter2. Then the new myCounter3 will reuse the backing instance of myCounter2, maintaining its internal state.

It is true that this could be avoided by using the following instead:

&& <CounterWithLifeCycleLog name={'myCounter2'} 
                    counter={this.state.counter2} />

The former example, however, is valid conditional rendering as well.

Proposed solution

An explicit mention of this confusion, an example involving conditional rendering (not using <li>, map(), or arrays), and perhaps a link to this blog post and perhaps the How to force remounting on React components related stackoverflow question.

Also, currently, all warnings related to keys seem to either have to do with arrays or iterators, perhaps a light warning when using conditional rendering could be helpful (though I can see how this will add way too much clutter), or some way to incorporate it into existing warnings.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず、keys、lists、reconciliation について説明している React ドキュメントのセクションを見つけます。提供されている conditional rendering の例を使って、map()、list items、arrays との違いを示します。ドキュメントで conditional rendering において keys が重要になる場合を明確に説明し、専用の例を含めれば作業は完了です。警告の変更は任意のスコープとして扱います。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript, react
領域
documentation
issue の種類
ドキュメント
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。