我正在开发一个本机应用程序并使用React路由器本机v4,我正在尝试开发动画部分,正如文档中所建议的那样,首先我确保一切都在没有动画或过渡的情况下工作。
我已经迭代了实现,这就像我现在所做的那样:
我的主要组件呈现以下内容:
// app.js:render
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
我的routes.js呈现以下内容(注意传递给Switch的位置道具以防止它在父组件之前更新其子节点):
// routes.js render
<ViewTransition pathname={location.pathname}>
<Switch location={location}>
<Route exact path={uri.views.main} component={Dashboard} />
<Route path={uri.views.login} component={Login} />
<Route path={uri.views.register} component={Register} />
</Switch>
</ViewTransition>
和处理动画的ViewTransition,现在它只是淡化/退出旧视图和新视图:
// view-transition.js
@withRouter
export default class ViewTransition extends Component {
static propTypes = {
children: PropTypes.node,
location: PropTypes.object.isRequired,
};
state = {
prevChildren: null,
opacity: new Animated.Value(1)
};
componentWillUpdate(nextProps) {
if (nextProps.location !== this.props.location) {
this.setState({ prevChildren: this.props.children }, this.animateFadeIn);
}
}
animateFadeIn = () => {
Animated.timing(this.state.opacity, {
toValue: 0,
duration: 150
}).start(this.animateFadeOut);
};
animateFadeOut = () => {
this.setState({ prevChildren: null }, () => {
Animated.timing(this.state.opacity, {
toValue: 1,
duration: 400
}).start();
});
};
render() {
const { children } = this.props;
const { prevChildren, opacity } = this.state;
return (
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
opacity,
position: "absolute"
}}
>
{prevChildren || children}
</Animated.View>
);
}
}
上面的代码正常工作,我可以看到旧视图逐渐消失,新视图渐渐消失,但是我有一个问题,当它开始淡出时,组件再次重新安装,我可以在动画开始之前看到一个闪烁,我想知道我的代码有什么问题。
答案 0 :(得分:0)
我可以修复上面的代码,碰巧在react组件生命周期中的方法componentWillUpdate已经将nextProps传递给了子节点,同时我的组件设置了旧子节点的新状态,Switch是准备新的渲染,生成一个旧的孩子和新孩子的装载,当最后我的组件完成设置状态,旧的孩子已经卸下,他们必须再次安装。
上面的故事是&#34;当我的动画开始时我可以看到一个眨眼&#34;,解决方案很容易,我不再检查componentWillUpdate
中的内容了但是在componentWillReceiveProps
中,由于新的props会在子组件之前传递给父组件,因此它给了我足够的时间来捕获当前子组件,将它们分配给状态,在Switch卸载它们之前渲染并将它们保存在视图中为了淡出,所以不再眨眼了。
我的最终观点 - transition.js:
// view-transition.js
export default class ViewTransition extends Component {
static propTypes = {
children: PropTypes.node,
location: PropTypes.object.isRequired,
};
state = {
prevChildren: null,
opacity: new Animated.Value(1)
};
componentWillReceiveProps(nextProps) {
if (nextProps.location !== this.props.location) {
this.setState({ prevChildren: this.props.children }, this.animateFadeIn);
}
}
animateFadeIn = () => {
Animated.timing(this.state.opacity, {
toValue: 0,
duration: 150
}).start(this.animateFadeOut);
};
animateFadeOut = () => {
this.setState({ prevChildren: null }, () => {
Animated.timing(this.state.opacity, {
toValue: 1,
duration: 400
}).start();
});
};
render() {
const { children } = this.props;
const { prevChildren, opacity } = this.state;
return (
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
opacity,
position: "absolute"
}}
>
{prevChildren || children}
</Animated.View>
);
}
}
答案 1 :(得分:0)
嗯..我知道为时已晚,也许您可以尝试react-router-native-animate-stack
它是react-router-native
的子组件。但是它是可动画的并提供堆栈功能。它受switch
组件的启发,如果您知道switch
,您将知道如何使用此软件包。
答案 2 :(得分:0)
我编写了一个AnimatedSwitch组件以在React Native中工作。
有一小段时间,状态正在更新,并且会闪烁,但是我使用以下代码修复了该问题:
// Need to render the previous route for the time between not animating and animating
if (needsAnimation && !animating) {
const tempPreviousRoute = getPreviousRoute(
exact,
previousLocation,
previousChildren,
);
if (tempPreviousRoute) {
const prevRouteComp = renderPreviousRoute(tempPreviousRoute);
return prevRouteComp;
} else {
return null;
}
}
完整的代码在这里。
https://javascriptrambling.blogspot.com/2020/07/react-router-native-animatedswitch.html