如何使用 React Material UI 的过渡组件来动画地将项目添加到列表中?

425*_*esp 6 javascript reactjs material-ui

我有这堂课。

class Demo extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      items: []
    };

    this.add = this.add.bind(this);
    this.clear = this.clear.bind(this);
  }

  add() {
    this.setState(prev => {
      const n = prev.items.length;
      return {
        items: [<li key={n}>Hello, World {n}!</li>, ...prev.items]
      };
    });
  }

  clear() {
    this.setState({ items: [] });
  }

  render() {
    return (
      <div>
        <div>
          <button onClick={this.add}>Add</button>
          <button onClick={this.clear}>Clear</button>
        </div>

        {/* This is wrong, not sure what to do though... */}
        <Collapse in={this.state.items.length > 0}>
          <ul>{this.state.items}</ul>
        </Collapse>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

沙盒链接:https : //codesandbox.io/s/material-demo-ggv04? file =/Demo.js

我试图做到这样,每次我单击“添加”按钮时,都会在列表顶部以动画形式存在一个新项目,并且现有项目被下推。不知道如何继续。

额外资源

Bru*_*iro 4

我更新了您的沙箱代码以实现您想要的目标,但我不认为 MaterialUI 是最好的库(我可能会错过更好的方法)。

挑战在于,当您添加新项目时,DOM 中尚不存在该项目。大多数动画库/组件都要求元素位于 DOM 中,它们只是通过过渡时间“隐藏”和“显示”它。

我也遇到过类似的情况,经过一些研究,我发现可以处理尚未在 DOM 中的元素的动画的更好的库是Framer Motion。(您可以查看他们的安装动画文档)

无论如何,这里是新代码沙盒的链接,您可以看一下。我所做的改变:

删除了随机密钥

map使用组件创建列表的函数中<Collapse />,有一个函数可以获取随机整数并将其分配key给您的组件。React 需要具有一致的密钥才能正确执行其伪装者操作,因此删除该随机数可以解决“切换”按钮动画不正确的问题。(如果您的项目列表没有唯一的 ID,则只需使用函数的索引map,这不是一个好的解决方案,但仍然比随机数更好)。

<Collapse key={i} timeout={this.state.collapseTimeout} in={this.state.open}>
    {it}
</Collapse>
Run Code Online (Sandbox Code Playgroud)

添加了一个新功能来控制切换

这里的方法是:将项目添加到列表中,然后在元素进入 DOM 后,关闭<Collapse />,稍等片刻,然后再次打开它(这样您就可以直观地看到动画)。为了做到这一点,我们需要一个新的“切换”函数,它可以显式设置折叠的值。

toggleValue(value) {
  this.setState(() => {
    return {
      open: value
    };
  });
}
Run Code Online (Sandbox Code Playgroud)

添加了崩溃的可变超时时间

最后一个问题是,<Collapse />添加新项目时关闭会触发动画来关闭它。这里的解决方案是动态更改崩溃的超时时间,因此您看不到这一点。

setCollapseTimeout(value) {
  this.setState(() => {
    return {
      collapseTimeout: value
    };
  });
}
Run Code Online (Sandbox Code Playgroud)

将元素添加到列表时,等待触发动画 同样,为了解决尚未在 DOM 中的元素的问题,我们需要使用 asetTimeout或其他东西来等待切换<Collapse />. 那已添加到您的add()函数中。

add() {
  this.toggleValue(false);
  this.setCollapseTimeout(0);
  this.setState(prev => {
    const n = prev.items.length;
    return {
      items: [<li key={n}>Hello, World {n}!</li>, ...prev.items]
    };
  });
  setTimeout(() => {
    this.setCollapseTimeout(300);
    this.toggleValue(true);
  }, 100);
}
Run Code Online (Sandbox Code Playgroud)

同样,这是一个让<Collapse />MaterialUI 能够处理尚未在 DOM 中的元素的 hacky 解决方案。但是,正如前面提到的,还有其他更好的库。

祝你好运 :)