javascript - 如何将 CSS 动画添加到 React 中特定的重新渲染项目?

标签 javascript reactjs

我需要在每次重新渲染项目状态的库存属性时播放 CSS 动画(增加按钮点击次数)

react 代码:

const RenderingApp = () => {
  const [items, setItems] = useState([
    { fruit: 'banana', stock: 10, id: 0 },
    { fruit: 'apple', stock: 5, id: 1 },
  ]);

  const renderList = () => {
    return items.map((item, index) => {
      const handleIncrease = () => {
        const newItems = items.map(i => {
          if (i.id === item.id) {
            return { ...i, stock: i.stock + 1 };
          } else {
            return i;
          }
        });
        setItems(newItems);
      };

      return (
        <div key={index}>
          <div>{item.fruit}</div>
          <div className="add-color">{item.stock}</div>
          <button onClick={handleIncrease}>increase</button>
          <br />
          <br />
        </div>
      );
    });
  };

  return <div>{renderList()}</div>;
};

CSS 代码:

.add-color {
  animation-name: example;
  animation-duration: 0.8s;
}

@keyframes example {
  0% {
    background-color: #fff;
  }
  50% {
    background-color: rgb(5, 149, 5);
  }
  100% {
    background-color: #fff;
  }
}

但是,动画在初始渲染时播放一次。为了解决这个问题,我在股票的 div 上添加了关键值,正如 question 中所回答的那样。 ,像这样:

 <div key={Math.random()} className="add-color">{item.stock}</div>

但是现在当我单击增加按钮时,例如第二个项目的按钮,两个股票的 div 都会重新渲染,因此动画会同时播放:

enter image description here下一步点击:enter image description here

在我添加键值之前,重新渲染仅发生在单击项目的库存 div 时,但未播放动画,但在添加键值后,两个项目的库存 div 都会发生重新渲染。

如何实现为刚刚单击的项目的库存 div 播放动画?提前致谢

最佳答案

你本质上想做的是 restart a CSS animation对于特定元素。老实说,我不确定在 React 中是否有比通过引用访问 DOM 元素更好的方法。

您可以通过将每个项目设为自己的组件并使用 useRef 来做到这一点访问您想要设置动画的 DOM 元素,然后应用上面链接的堆栈溢出答案中的动画代码。

const RenderItem = ({ item, handleIncrease }) => {
    const stockElem = useRef()

    const animate = () => {
        let s = stockElem.current
        s.style.animation = 'none'
        // I had to do "let x =" here because my create-react-app config was yelling at me
        let x = s.offsetHeight; // trigger reflow
        s.style.animation = null
    }

    const increase = () => {
        handleIncrease()
        animate()
    }

    return (
        <div>
            <div>{item.fruit}</div>
            <div ref={stockElem} className="add-color">{item.stock}</div>
            <button onClick={increase}>increase</button>
            <br />
            <br />
        </div>
    )
}

然后在主组件中渲染每个项目:

return <RenderItem key={item.id} item={item} handleIncrease={handleIncrease} />;

key方法

有一种方法可以用 key 来做到这一点,但我不喜欢它,因为它违背 key React 定义的目的,并且可能会导致以后出现问题。

return (
  <div key={`${item.id}-${item.stock}`}>
    <div>{item.fruit}</div>
    <div className="add-color">{item.stock}</div>
    <button onClick={handleIncrease}>increase</button>
    <br />
    <br />
  </div>
);

关键行是<div key={`${item.id}-${item.stock}`}> 。 React 将卸载并重新安装键发生变化的元素。因此,这利用了 item.id 的唯一性结合以下事实:item.stock更改以重新呈现 div。

再说一次,尽管我提供的第一个解决方案更加冗长,但它绝对更加规范。

关于javascript - 如何将 CSS 动画添加到 React 中特定的重新渲染项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68741403/

相关文章:

javascript - 折叠所有菜单并同时隐藏它们?

javascript - 如何在 React 中触发原生事件?

reactjs - 清除异步选择上的缓存选项

javascript - 如何处理来自复杂 Angular.js Web 表单的提交数据

javascript - 如何捕获动态创建的按钮的点击? jQuery

javascript - 文本/模板和文本/纯文本有什么区别?

javascript - 获取div的高度而不是窗口的高度

reactjs - 我想使用 ant design 的 React 来验证密码

javascript - 无法在 React 中获得真实的元素高度

javascript - Protractor browser.wait 不等待