当用动态键包裹在 div 中时,React Collapse 过渡不会动画
React Collapse transition doesn't animate when wrapped in a div with a dynamic key
这真的很奇怪。我花了很多时间才弄清楚如何 解决这个问题。但即使修复了它,我也不知道为什么它在一种配置中损坏,但在另一种配置中却没有。
最好的解释方法是使用 StackBlitz 实例:https://stackblitz.com/edit/react-collapse-transition-breaks-with-dynamic-key
实例详细说明了确切的问题,但这里是概要:
- 这是一个使用 Material UI.
的 React 应用程序
- 我有一个
,其中填充了一个 数组。
- 那些
是可点击的。当您单击它们时,它会使用 转换来显示 "subheaders" 的子 。子标题 也填充了 数组。
- 这就是它变得奇怪的地方:我有一个简单的 包含 "header"
和 - "subheaders". 的 ible <列表>
- 因为它们是数组的一部分,如果我没有将 "key" 属性添加到 top-level 元素 (),React 会抱怨。
- 如果我将 a dynamically-generated 键值 添加到包含 的那个,它会以某种方式终止
元素上的过渡动画。 仍然是 opens-and-closes,但它不会在设定的毫秒数内进行动画处理。它只是打开(立即)或关闭(立即)。
- 如果我将 静态键值 添加到包含 的相同键值中,动画效果很好。
为什么dynamic-key方法会破坏动画?
TLDR:在 React 中不要 dynamically-generate globally-unique 数组元素的键。
好的,经过多次谷歌搜索,我想我终于明白是怎么回事了。
当您在 React 中向数组添加项目时,如果您没有向数组中的每个元素添加唯一的 "key",则会引发警告。只要您使用 something unique 作为每个元素的 "key" 值,警告就会消失,并且在大多数情况下,React 似乎可以很好地管理数组元素。
当我开始 React 开发时(几年前),我想,“我可以通过使用随机 GUID-generating 函数向我的所有数组元素添加唯一键来轻松解决这个问题。所以我会经常使用如下代码:
let newArray = [];
someMasterArrayOfObjects.forEach(object => {
if (someConditionIsMet) {
// SEE HOW CLEVER I THOUGHT I WAS?? USING A RANDOMLY-GENERATED GUID QUIETS THE
// UNIQUE-KEY WARNINGS THAT ARE THROWN BY REACT
newArray.push(
<div key={createRandomGuid()}>
{object.title}
</div>
);
}
});
但是我错过了 ReactJS 文档中的一个关键词(强调,我的):
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a STABLE identity:
他们在文档中多次使用 "stable" 这个词,但我并没有真正理解它。像大多数开发人员一样,我首先关心的是删除数组元素缺少唯一键时抛出的警告。使用 randomly-generated GUID 解决了这个问题。
但是 React 使用这些键来确定在状态更改期间应该 re-rendered 什么。如果你每次在数组中构建元素时 randomly-generate 一个新的 globally-unique 键,那么 React 将假设所有这些元素都需要在你每次设置状态时从头开始完全重建。
至少,这是低效的。您可能不会注意到小 arrays/apps 中的任何性能影响,但没有理由人为地 force a re-rendering of every数组元素 每 一次出于任何原因设置该状态。您可能不会注意到您的应用程序中有任何视觉问题,但这是一种糟糕的做法。
在最坏的情况下,它实际上会破坏您的某些功能。在我的例子中,它打破了 过渡动画,因为渲染引擎无法比较一个状态变化和下一个状态变化之间增加的 "height" 值 - 因为每次尝试改变那个高度时,我都在分配一个"key" 值的全新 globally-unique 标识符,React 将其视为一个全新的、完全不同的组件。
一旦我终于弄明白要做什么 Google,我还发现了这个很棒的 JSFiddle:
http://jsfiddle.net/frosas/S4Dju/
请注意,他的示例中输入的中间行标题为 "Unique random keys"。当您手动更改其中一个 唯一随机键 的值时,然后单击 "Add item",它会破坏您更改的结果,因为它 re-renders 输入元素作为 brand-new 元素,与其先前的状态无关。
这真的很奇怪。我花了很多时间才弄清楚如何 解决这个问题。但即使修复了它,我也不知道为什么它在一种配置中损坏,但在另一种配置中却没有。
最好的解释方法是使用 StackBlitz 实例:https://stackblitz.com/edit/react-collapse-transition-breaks-with-dynamic-key
实例详细说明了确切的问题,但这里是概要:
- 这是一个使用 Material UI. 的 React 应用程序
- 我有一个
- ,其中填充了一个
数组。 - 那些
是可点击的。当您单击它们时,它会使用 转换来显示 "subheaders" 的子 - 。子标题
- 也填充了
数组。 - 这就是它变得奇怪的地方:我有一个简单的 包含 "header"
和 - "subheaders". 的 ible <列表> - 因为它们是数组的一部分,如果我没有将 "key" 属性添加到 top-level 元素 (
),React 会抱怨。- 如果我将 a dynamically-generated 键值 添加到包含
的那个,它会以某种方式终止元素上的过渡动画。 仍然是 opens-and-closes,但它不会在设定的毫秒数内进行动画处理。它只是打开(立即)或关闭(立即)。 - 如果我将 静态键值 添加到包含
的相同键值中,动画效果很好。为什么dynamic-key方法会破坏动画?
TLDR:在 React 中不要 dynamically-generate globally-unique 数组元素的键。
好的,经过多次谷歌搜索,我想我终于明白是怎么回事了。
当您在 React 中向数组添加项目时,如果您没有向数组中的每个元素添加唯一的 "key",则会引发警告。只要您使用 something unique 作为每个元素的 "key" 值,警告就会消失,并且在大多数情况下,React 似乎可以很好地管理数组元素。
当我开始 React 开发时(几年前),我想,“我可以通过使用随机 GUID-generating 函数向我的所有数组元素添加唯一键来轻松解决这个问题。所以我会经常使用如下代码:
let newArray = []; someMasterArrayOfObjects.forEach(object => { if (someConditionIsMet) { // SEE HOW CLEVER I THOUGHT I WAS?? USING A RANDOMLY-GENERATED GUID QUIETS THE // UNIQUE-KEY WARNINGS THAT ARE THROWN BY REACT newArray.push( <div key={createRandomGuid()}> {object.title} </div> ); } });
但是我错过了 ReactJS 文档中的一个关键词(强调,我的):
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a STABLE identity:
他们在文档中多次使用 "stable" 这个词,但我并没有真正理解它。像大多数开发人员一样,我首先关心的是删除数组元素缺少唯一键时抛出的警告。使用 randomly-generated GUID 解决了这个问题。
但是 React 使用这些键来确定在状态更改期间应该 re-rendered 什么。如果你每次在数组中构建元素时 randomly-generate 一个新的 globally-unique 键,那么 React 将假设所有这些元素都需要在你每次设置状态时从头开始完全重建。
至少,这是低效的。您可能不会注意到小 arrays/apps 中的任何性能影响,但没有理由人为地 force a re-rendering of every数组元素 每 一次出于任何原因设置该状态。您可能不会注意到您的应用程序中有任何视觉问题,但这是一种糟糕的做法。
在最坏的情况下,它实际上会破坏您的某些功能。在我的例子中,它打破了
过渡动画,因为渲染引擎无法比较一个状态变化和下一个状态变化之间增加的 "height" 值 - 因为每次尝试改变那个高度时,我都在分配一个"key" 值的全新 globally-unique 标识符,React 将其视为一个全新的、完全不同的组件。 一旦我终于弄明白要做什么 Google,我还发现了这个很棒的 JSFiddle:
http://jsfiddle.net/frosas/S4Dju/
请注意,他的示例中输入的中间行标题为 "Unique random keys"。当您手动更改其中一个 唯一随机键 的值时,然后单击 "Add item",它会破坏您更改的结果,因为它 re-renders 输入元素作为 brand-new 元素,与其先前的状态无关。
- 因为它们是数组的一部分,如果我没有将 "key" 属性添加到 top-level 元素 (