我正在使用新的_app.js
文件供Next.js尝试创建页面过渡,例如淡入淡出或滑动,但无法解决。我正在使用样式化组件来应用样式。我的结构目前看起来像这样:
_app.js
import App, { Container } from 'next/app';
import React from 'react';
import PageTransition from '../components/PageTransition';
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<PageTransition>
<Component {...pageProps} />
</PageTransition>
</Container>
);
}
}
export default MyApp;
components / PageTransition / index.jsx
import { Transition } from 'react-transition-group';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Root from './index.style';
class PageTransition extends Component {
state = {
active: true,
}
componentDidUpdate() {
// Check if children are different to previous children
// If true, set this.state.active to false
// After 1000ms transition, set to true again
}
render() {
const { children } = this.props;
const { active } = this.state;
return (
<Transition in timeout={1000}>
<Root id="root" active={active}>
{children}
</Root>
</Transition>
);
}
}
export default PageTransition;
components / PageTransition / index.style.js
import styled from 'styled-components';
const Root = styled.div`
opacity: ${p => (p.active ? 1 : 0)};
transition: opacity 1000ms;
`;
export default Root;
这是正确的方法吗?如果是这样,我认为componentDidUpdate不足以赶上页面更改。我尝试进行这项工作,但它会渲染,您会在状态再次更新之前看到页面的闪烁,以告诉它开始淡出然后淡入。我需要在渲染之前更新状态。
有没有办法通过React Transition Group来解决?我确实看过next-page-transitions,但是对于该软件包使用率低感到不满意,我只想找到一个更简单的解决方案。
答案 0 :(得分:0)
我尝试进行这项工作,但是它会渲染,您会在状态再次更新之前看到页面的闪烁,以告诉它开始淡出然后淡入。我需要在渲染之前更新状态。 / p>
可以通过以下方法解决此问题:默认情况下,将display: none
放在组件上,然后在页面完全呈现后显示它,并在需要时应用动画
答案 1 :(得分:0)
我最近也在研究如何实现这一目标。翻阅下一页过渡的简要文档,实现简单的淡入/淡出页过渡就像在App组件render方法中使用此过渡一样简单:
render() {
const { Component, pageProps } = this.props
return (
<Container>
<PageTransition timeout={300} classNames="page-transition">
<Component {...pageProps} />
</PageTransition>
<style jsx global>{`
.page-transition-enter {
opacity: 0;
}
.page-transition-enter-active {
opacity: 1;
transition: opacity 300ms;
}
.page-transition-exit {
opacity: 1;
}
.page-transition-exit-active {
opacity: 0;
transition: opacity 300ms;
}
`}</style>
</Container>
)
}
但是,我看到您正在尝试使用react-transition-group。如果您希望获得更复杂的动画,则将使用该库。
这是我使用react-transition-group进行的快速测试的App组件渲染方法的示例:
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<div ref={x => (this.comp = x)}>
<TransitionGroup>
<Transition
in={this.props.in}
key={this.props.router.route}
timeout={{
enter: 2000,
exit: 2000
}}
mountOnEnter={false}
unmountOnExit={true}
onEnter={this.enterTransition}
>
<Component {...pageProps} />
</Transition>
</TransitionGroup>
</div>
</Container>
);
}
注意:我正在使用GSAP进行动画处理,在此测试中,我需要在初始安装时引用组件的内容。如果不需要此功能,则可以删除该div,然后确保为onEnter提供一个在每次页面导航时都会调用的函数。
enterTransition = node => {
TweenMax.fromTo(node, 0, { x: 0, opacity: 0 }, {x: 200, opacity: 1});
}
该节点将是下一个要安装的组件。 还有一个onExit挂钩,您可以使用该挂钩以类似的方式定位退出节点。
答案 2 :(得分:0)
使用 key
....
Key
仅在 route
更改时触发页面更改转换。
你可以这样做:
render() {
const { Component, pageProps, router } = this.props;
return (
<Container>
<PageTransition>
<Component {...pageProps} key={router.route} />
</PageTransition>
</Container>
);
}