更新
对于那些面临同样问题的人:我发现在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;
}
答案 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>
);
}