reactjs / reactjs/react.dev

Highlight Possible Necessity of keys for Conditional Rendering

未关闭
#1,779 0 条评论 5 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
JavaScript
星标
11.8k
派生
7.9k
平均合并
1 天 11 小时
30 天内合并 PR
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. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先找到 React 文档中解释 keys、lists 和 reconciliation 的部分。使用提供的 conditional-rendering 示例来说明它与 map()、列表项和数组之间的区别。当文档清楚解释 keys 在 conditional rendering 中何时重要,并包含一个专门的示例时,这项工作就完成了;任何警告更改都视为可选范围。

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript, react
领域
documentation
Issue 类型
文档
难度
3/5
预计耗时
1-2 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。