React CSSTransition退出时使用的错误类

时间:2018-02-07 02:52:28

标签: reactjs react-transition-group

更新

对于那些面临同样问题的人:我发现在ReactTransitionGroup的git页面上发布了一个类似的问题,其中包含解决方案:https://github.com/reactjs/react-transition-group/issues/182

说实话,90%的解决方案都在我脑海中吹嘘,我根本不了解它,这是唯一对我有意义的部分(取自React TransitionGroup and React.cloneElement do not send updated props链接git问题):

  

通过道具离开孩子?   现在的问题是,为什么没有更新道具传递给离开元素?那么,它会如何获得道具?道具从父组件传递到子组件。如果查看上面的示例JSX,您可以看到leave元素处于分离状态。它没有父级,只是因为它将其存储在状态而被渲染。

我必须进一步研究和理解父母和孩子组成部分的沟通方式。我仍然是网络开发的新手,但事情正在慢慢开始变得有意义。

------------------

提出初步问题:

当你试图通过React.cloneElement向你的孩子注入状态时,离开的组件不是那些孩子中的一个。

我有一个小应用程序,其中包含一个导航菜单和嵌套在交换机容器之间的路由。每次单击导航项时,我都会检查索引是高还是低,以相应地设置动画状态(左或右),然后存储单击的导航项的新索引。

每次切换路线时,应用的动画都是淡入淡出或淡入淡出。现在一切正常,但唯一的问题是当类从左向左切换时,应用的EXIT动画使用前面给出的类。

我理解为什么会发生这种情况,这是因为使用的退出类是最初设置的,当新类仅应用于第二次更改时,新的退出会生效。转换文档非常有限,我找不到任何内容。

const { Component } = React;
const { TransitionGroup, CSSTransition } = ReactTransitionGroup;
const { HashRouter, Route, NavLink, Switch, withRouter } = ReactRouterDOM;

var icons = [
 {icon: 'far fa-address-book active', path: '/'},
 {icon: 'fab fa-linkedin', path: '/linked'},
 {icon: 'fas fa-gamepad', path: '/hobbies'}
];

const Nav = props => {
  return (
   <div className="nav">
    <ul>
      { 
        icons.map((icon, index) => {
          return (
            <li
              key={index}
              onClick={() => props.clicked(index)}
              className={props.active == index ? 'active' : false}>
                <NavLink to={icon.path} className="NavLink">
                  <i className={icon.icon} key={icon.icon}></i>
                </NavLink>
            </li>
          );
        })
      }
    </ul>
  </div>
);
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentViewIndex: 0,
      animationDirection: 'right'
    }

   this.setIndex = this.setIndex.bind(this);
 }

 setIndex(index){
   const animationDirection = index < this.state.currentViewIndex ? 'left' : 'right';
   this.setState({currentViewIndex: index, animationDirection});
 }

  render () {
    const { location } = this.props;

    return (
      <div className="container">
        <Nav active={this.state.currentViewIndex} clicked={() => this.setIndex()} />
        <TransitionGroup>
          <CSSTransition
            key={location.pathname}
            classNames={`fade-${this.state.animationDirection}`}
            timeout={1000}>
            <Switch location={location}>
              <Route exact path="/" render={() => <h1>Home</h2>} />
              <Route path="/linked" render={() => <h1>Linked</h2>} />
              <Route path="/hobbies" render={() => <h1>Hobbies</h2>} />
            </Switch>
          </CSSTransition>
        </TransitionGroup>
      </div>
    );
   }
 }

const AppWithRouter = withRouter(App);

ReactDOM.render(<HashRouter><AppWithRouter /></HashRouter>, document.querySelector('#root'));

应用于过渡的CSS类:

.fade-left-enter {
  position: unset;
  transform: translateX(-320px);
}

.fade-left-enter.fade-left-enter-active {
  position: unset;
  transform: translateX(0);
  transition: transform .5s ease-in;
}

.fade-left-exit {
  position: absolute;
  bottom: 0;
  transform: translateX(0);
}

.fade-left-exit.fade-left-exit-active {
  transform: translateX(320px);
  transition: transform .5s ease-in;
}

.fade-right-enter {
  position: unset;
  transform: translateX(320px);
} 

.fade-right-enter.fade-right-enter-active {
  position: unset;
  transform: translateX(0);
  transition: transform .5s ease-in;
}

.fade-right-exit {
  position: absolute;
  bottom: 0;
  transform: translateX(0);
}

.fade-right-exit.fade-right-exit-active {
  transform: translateX(-320px);
  transition: transform .5s ease-in;
}

1 个答案:

答案 0 :(得分:4)

您遇到问题的原因是退出组件已经分离,因此无法获得任何更新。您可以找到有关问题的非常好的解释here

您可以使用<TransitionGroup>中的道具childFactory来解决此问题:

  

childFactory

     

您可能需要在孩子退出时对其应用反应性更新。   这通常通过使用cloneElement来完成,但是在   退出子元素已被删除且无法访问   对消费者而言。

     

如果你确实需要更新孩子,你可以提供一个   childFactory包装每个孩子,甚至是那些离开的孩子。

在渲染方法中尝试以下代码更改:

render () {
  const { location } = this.props;

  const classNames = `fade-${this.state.animationDirection}`; // <- change here

  return (
    <div className="container">
      <Nav active={this.state.currentViewIndex} clicked={() => this.setIndex()} />
      <TransitionGroup 
        childFactory={child => React.cloneElement(child, { classNames })} // <- change here
      >
        <CSSTransition
          key={location.pathname}
          classNames={classNames} // <- change here
          timeout={1000}
        >
            <Switch location={location}>
              <Route exact path="/" render={() => <h1>Home</h2>} />
              <Route path="/linked" render={() => <h1>Linked</h2>} />
              <Route path="/hobbies" render={() => <h1>Hobbies</h2>} />
            </Switch>
        </CSSTransition>
      </TransitionGroup>
    </div>
  );

}