简体   繁体   English

使用react-transition-group在转换之前元素值移位和更改

[英]Element values shifting and changing before transition with react-transition-group

I noticed this behavior while using the react-transition-group package in a gatsby project I'm working on. 在我正在研究的gatsby项目中使用react-transition-group包时,我注意到了这种行为。 I have a list of "tags" that are added to an active list as they are picked from another master list. 我有一个“标签”列表,当从另一个主列表中选择时,它们会添加到活动列表中。 Clicking a tag from the master list adds it to the active list, and clicking a tag from the active list removes it. 单击主列表中的标记会将其添加到活动列表中,单击活动列表中的标记会将其删除。 Pretty much how you would expect something like this to work. 几乎你会期望这样的东西起作用。

The transition in works just fine, but when transitioning out the tags re-organize themselves in a strange way. 作品的过渡就好了,但转的标签时,在一个陌生的方式重新组织起来。 We have five tags with the following values: 我们有五个标签,其中包含以下值:

  • Dairy Free 无乳制品
  • Party Food 派对食物
  • Family Sized 家庭规模
  • Low Cholesterol 低胆固醇
  • Low Sodium 低钠

If you click the Family Sized tag to remove it, the following occurs: 如果单击Family Sized标记将其删除,则会发生以下情况:

  1. Family Sized disappears instantly Family Sized立即消失
  2. Low Cholesterol and Low Sodium shift instantly to the left Low CholesterolLow Sodium立即向左移动
  3. The last tag changes to Low Sodium instantly 最后一个标签立即变为Low Sodium
  4. The last tag, now with the value of Low Sodium transitions out 最后一个标签,现在具有Low Sodium的值

The expected behavior is that the Family Sized tag transitions out from where it is in the middle of the group. 预期的行为是Family Sized标签从组中间的位置转换出来。 I should note that it works fine if you remove the last tag from the active list, this only happens when removing a tag from any other position. 我应该注意,如果从活动列表中删除最后一个标记,它会正常工作,这只有在从任何其他位置删除标记时才会发生。

Here is a slowed-down GIF of the transition and here is my code: 这是转换的慢速GIF ,这是我的代码:

<TransitionGroup className='tag-container'>
  {filter.map((tag, index) => {
    return (
      <CSSTransition key={index} timeout={250} classNames={`tag`}>
        <TagButton value={tag} onClick={onClickFunction} className={`${screenStyle} active`}>{tag}</TagButton>
      </CSSTransition>
    )
  })}
</TransitionGroup>
  • filter is an array destructured from the component's state. filter是一个从组件状态中解析出来的数组。
  • There is a <StaticQuery> from gatsby used in the same render() method of the component if that matters. 如果重要的话, gatsby中的<StaticQuery>gatsby的相同render()方法中使用。
  • The <TagButton> is a styled component from styled-components package, not a separately imported component. <TagButton>是样式styled-components包中的styled-components ,而不是单独导入的组件。

Adding specific identifier in your array and setting key of each element to each identifier in map method will solve your problem. 在数组中添加特定标识符并将每个元素的键设置为map方法中的每个标识符将解决您的问题。

import React from "react";
import ReactDOM from "react-dom";
import { Button } from "react-bootstrap";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import "bootstrap/dist/css/bootstrap.css";
import "./styles.css";
import uuid from "uuid";

function App() {
  const [items, setitems] = React.useState([
    { id: uuid(), name: "Dairy Free" },
    { id: uuid(), name: "Party Food" },
    { id: uuid(), name: "Family Sized" },
    { id: uuid(), name: "Low Cholesterol" },
    { id: uuid(), name: "Low Sodium" }
  ]);
  const removeitem = item => {
    setitems(items.filter(itemname => itemname.id !== item));
  };
  return (
    <div className="App">
      <TransitionGroup className="todo-list">
        {items.map(data => (
          <CSSTransition timeout={500} classNames="item" key={data.id}>
            <Button className="m-2" onClick={() => removeitem(data.id)}>
              {data.name}
            </Button>
          </CSSTransition>
        ))}
      </TransitionGroup>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

This problem is already solved here , so please checkout to understand this strange behavior. 这个问题已在这里解决,所以请结账以了解这种奇怪的行为。

For future reference if anyone comes across this. 如果有人遇到此问题,以备将来参考。 The issue was with how the key value was being passed to the tags. 问题在于如何将key传递给标记。

My code was mapping through the filter array and assigning the index of each value as the child components' keys. 我的代码通过filter数组进行映射,并将每个值的index指定为子组件的键。 This means they are keyed as 0, 1, 2, 3, etc. When a tag is removed from the filter array and the page re-renders, the indexes are re-applied in whatever order the array is in, which means that they all shift instead of the one that was removed being "plucked out" from wherever it was. 这意味着它们被键入为0,1,2,3等。当从filter数组中删除标记并重新呈现页面时,将按照数组所处的顺序重新应用索引,这意味着它们所有转移而不是被移除的那个从任何地方被“拔出”。

The solution was to use a unique key that doesn't rely on the array's index values at all. 解决方案是使用一个完全不依赖于数组索引值的唯一键。 Here is what I updated to: 这是我更新的内容:

<TransitionGroup className='tag-container'>
  {filter.map((tag) => {
    return (
      <CSSTransition key={`active_${tag}`} timeout={250} classNames={`tag`}>
        <TagButton value={tag} onClick={onClickFunction} className={`${screenStyle} active`}>{tag}</TagButton>
      </CSSTransition>
    )
  })}
</TransitionGroup>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM