1. ホーム
  2. javascript

[解決済み] React Material UI のトランジション コンポーネントを使用して、リストに項目を追加するアニメーションを作成するにはどうすればよいですか?

2022-02-24 07:46:56

質問

このようなクラスがあります。

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>
    );
  }
}

サンドボックスのリンクです。 https://codesandbox.io/s/material-demo-ggv04?file=/Demo.js

私は、"add" ボタンをクリックするたびに、新しいアイテムがリストの一番上にアニメーションで存在するようになり、既存のアイテムが下に押し出されるようにしようとしています。しかし、どのように進めればいいのかわかりません。

追加リソース

解決方法は?

サンドボックスのコードを更新して、ご希望に沿うようにしましたが、MaterialUIがそのための最適なライブラリとは思えません(もっと良い方法を見逃しているかもしれませんが)。

課題は、新しいアイテムを追加するとき、それがまだDOMに存在しないことです。そして、これらのアニメーションライブラリ/コンポーネントのほとんどは、要素がDOMに存在することを必要とし、それらは単に"hide"と遷移時間と共に"show"を行うだけです。

私も同じような状況でしたが、いろいろ調べた結果、まだ DOM にない要素のアニメーションを扱えるより良いライブラリは フレーマーモーション . (彼らのドキュメントを確認するには マウントアニメーション )

とにかく、以下は、新しい コード・サンドボックス ので、見てみてください。私が行った変更点

ランダムキーの削除

map を使用してリストを作成する関数です。 <Collapse /> コンポーネントで、ランダムな整数を取得し、それを key をコンポーネントに追加します。React が適切にふりをするためには一貫したキーが必要なので、この乱数を削除することで "Toggle" ボタンが適切にアニメーションしない問題が修正されました。(アイテムのリストにユニークなIDがない場合は、単に map 関数は、良い解決策とは言えませんが、乱数よりはましです)。

<Collapse key={i} timeout={this.state.collapseTimeout} in={this.state.open}>
    {it}
</Collapse>

トグルを制御するための新機能を追加

ここでのアプローチは、リストにアイテムを追加し、その要素が DOM 内にある後に <Collapse /> 少し待ってからもう一度開いてください(視覚的にアニメーションを見ることができるように)。そのためには、collapse の値を明示的に設定できる新しい "toggle" 関数が必要でした。

toggleValue(value) {
  this.setState(() => {
    return {
      open: value
    };
  });
}

崩壊時のタイムアウトを可変にしました

最後の問題は <Collapse /> 新しいアイテムが追加されたとき、それを閉じるためのアニメーションがトリガーされていました。この解決策は、折りたたみのタイムアウトを動的に変更することで、そのようなことが起こらないようにしました。

setCollapseTimeout(value) {
  this.setState(() => {
    return {
      collapseTimeout: value
    };
  });
}

要素をリストに追加するときは、アニメーションを起動するのを待ちます。 ここでも、まだ DOM に入っていない要素に関する問題を回避するために setTimeout をトグルするために待機する、あるいは <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);
}


を作るという、これまたハチャメチャな解決策。 <Collapse /> のMaterialUIは、まだDOMにない要素で動作します。しかし、前述のように、そのためのより良いライブラリが他にあります。

がんばってください :)