2017-04-20 13 views
2

背景それぞれがコレクションから削除できる要素のコレクションのコンテナを作成しようとしています。要素が削除されると、その出口をアニメートしたいと思い、React Motionを使用してこれを達成しようとしています。ここでリアクションモーションで要素の終了をアニメーション化する(親要素からこれらの要素を受け取る)

は、上記の図です:

enter image description here

問題私は、モーションのTransitionMotionコンポーネントを反応させるの使用を考え、それに渡される必要がある関数を記述しようとして捕まってしまいました。

class Container extends Component { 

    state = { 
    elementStyles: {} 
    } 

    componentDidMount() { 
    this.getElementStyles(); 
    } 

    componentDidUpdate() { 
    this.getElementStyles(); 
    } 

    getElementStyles() { 
    if (!this.props.children.length || this.hasElementStyles()) return; 

    // this assumes all elements passed to the container are of equal dimensions 
    let firstChild = this.refs.scroller.firstChild; 

    let elementStyles = { 
     width: firstChild.offsetWidth, 
     height: firstChild.offsetHeight, 
     opacity: 1 
    }; 

    this.setState({ 
     elementStyles 
    }); 
    } 


    hasElementStyles() { 
    return !isEmpty(this.state.elementStyles); // lodash to the rescue 
    } 

    willLeave() { 
    return { width: spring(0), height: spring(0), opacity: spring(0) } 
    } 

    getChildrenArray() { 
    return Children.toArray(this.props.children); // that's React's util function 
    } 

    getModifiedChild(element, props) { 
    if (!element) return; 

    return React.cloneElement(
     element, 
     {style: props.style} 
    ); 
    } 

    getInitialTransitionStyles() { 
    let elements = this.getChildrenArray(); 
    let result = elements.map((element, index) => ({ 
     key: element.key, 
     style: this.state.elementStyles 
    })); 
    return result; 
    } 

    render() { 
    if (this.hasElementStyles()) { 

     return (
     <TransitionMotion 
      willLeave={this.willLeave} 
      styles={this.getInitialTransitionStyles()} 
     > 
      { interpolatedStyles => { 
       let children = this.getChildrenArray(); 
       return <div ref="scroller" className="container"> 
       { interpolatedStyles.map((style, index) => { 
        return this.getModifiedChild(children[index], style); 
        }) 
       } 
       </div> 
      }} 
     </TransitionMotion> 
    ); 
    } else { 
     return (
     <div ref="scroller" className="container"> 
      { this.props.children } 
     </div> 
    ); 
    } 
    } 

} 

お知らせTransitionMotionコンポーネント内のマップ関数内の行::return this.getModifiedChild(children[index], style) - 間違った - ここに私のコードです。要素がコレクションから削除されると、this.props.childrenが変更されますので、間違っている、とchildren配列のインデックスは、もは​​や子どもたちから算出しstyles配列のインデックスに対応していないでしょう。

私が必要とするのは、要素がコレクションから削除される前と後でprops.childrenを追跡するための巧妙な方法です(そして、私は考えることができません;私が考え出すことができる最高のものは、find配列return this.getModifiedChild(children.find(child => child.key === style.key), style);の機能が、それは)それについて考えるために、私は怖いループ内で非常に多くのループになります、またはいくつかの完全に異なるアプローチを使用するために、私は知りません。助けてもらえますか?

答えて

1

この溶液の削除アニメーションは、水平方向(それは低いZインデックス情報を使用して)左のカードの下に左削除項目(及び行の「カード」の残りの部分)をスライドさせます。

最初の行として<モーション/>タグとカード表示設定をレンダリングします。

各カードの株式配列要素のインデックスをsetStates、配列をスライスタイマーを開始削除ボタン方式。 setStateは、タイマーがスライスを実行する前にカードをアニメーション化するレンダーをトリガーします。それについてです

class CardRow extends React.PureComponent { 
 

 
    constructor(props) { 
 
     super(props); 
 
     this.state = { 
 
      cardToRemove: 99, 
 
     }; 
 
    } 
 

 
    findCard = (_id) => { 
 
     return this.myArray.find((_card) => { 
 
      return _card.id === _id; 
 
     }); 
 
    }; 
 

 
    removeCardClick = (evt) => { 
 
     const _card = this.findCard(evt.target.id); 
 

 
     setTimeout(() => { // wait for the render... 
 
      this.myArray.splice(this.myArray.indexOf(_card), 1); 
 
      this.setState({cardToRemove: 99}); 
 
     }, 200); 
 

 
     this.setState({cardToRemove: this.myArray.indexOf(_card)}); 
 
    }; 
 

 
    render() { 
 
     let items = this.myArray.map((item, index) => { 
 

 
      let itemLeft = 200 * index;  // card width 200px 
 
      if (this.state.cardToRemove <= index) { 
 
       itemLeft = 200 * (index - 1); 
 
      } 
 

 
      // .cardContainer {position: fixed} 
 
      return <div key={item.id}> 
 
       <Motion style={{left: spring(itemLeft)}}> 
 
        {({left}) => 
 
         <div className="cardContainer" style={{left: left}}> 
 
          <div className="card"> 
 
           <button className="Button" id={item.id} onClick={this.removeCardClick}>Del</button> 
 
          </div> 
 
         </div> 
 
        } 
 
       </Motion> 
 
      </div>; 
 
     }); 
 

 
     items = items.reverse(); 
 

 
     return <div> 
 
      {items} 
 
     </div>; 
 
    } 
 
}

!おかげで、お楽しみください、

関連する問題