如何正确实现页面过渡的React Transition Group

时间:2019-09-12 01:48:59

标签: reactjs react-router react-router-v4 react-router-dom react-transition-group

我整天都在扯头发,试图使它起作用。我要注意的是,由于某种原因,过渡类(classNames =“ fade”)永远不会应用于页面元素。因此,当我从一个页面导航到另一页面时,将短暂显示两个页面组件(超时时间)。

我应该在600毫秒内拥有什么...

<div class="RTG"> 
    <div class="page fade-appear fade-enter fade-enter-active"> <!-- 
destination component HTML --></div>
    <div class="page fade-exit fade-exit-active"> <!-- start component HTML --></div>
</div>

我得到的是..

<div class="RTG">
   <!-- "fade..." classes never applied to the child nodes" -->
   <div class="page"> <!-- destination component HTML --></div>
   <div class="page"> <!-- start component HTML --></div>
</div>

然后在600ms超时后,我就剩下...

<div class="RTG">
   <div class="page"> <!-- destination component HTML --></div>
</div>

注意1 :我将“ RTG” className放在TransitionGroup组件上只是为了验证我的“ page”类组件实际上是TransitionGroup组件的直接后代。由于任何其他原因不存在。

注意2 :我使用的是react-transition-group@2.4.0,因为我与最新版本存在兼容性问题。

AppRouter.js

import PrivateRoute from './PrivateRoute';
import PublicRoute from './PublicRoute';
import { CSSTransition, TransitionGroup } from 'react-transition-group'



const AppRouter = () => (
    <Router history={history}>
        <Route render={({location}) => {
            return (
                <TransitionGroup className="RTG">
                <CSSTransition 
                    key={location.key}
                    timeout={600}
                    classNames="fade"
                >
                    <Switch location={location}>
                        <PublicRoute path="/" component={LoginPage} exact={true} />
                        <PrivateRoute path="/dashboard" component={ExpenseDashboardPage} />
                        <PrivateRoute path="/create" component={AddExpensePage} />
                        <PrivateRoute path="/edit/:id" component={EditExpensePage} />
                        <Route component={NotFoundPage} />
                    </Switch>
                </CSSTransition>
           </TransitionGroup>
            );
        }} />

    </Router>
);


export default AppRouter;

PrivateRoute.js

export const PrivateRoute = ({ 
    isAuthenticated, 
    component: Component,
    ...rest
}) => (
    <Route {...rest} component={(props) => (
        isAuthenticated ? (
            <div className="page">
                <Header />
                <Component {...props} />
            </div>
        ) : (
            <Redirect to="/" />
        )
    )} />
);

const mapStateToProps = (state) => ({
    isAuthenticated: !!state.auth.uid
});

export default connect(mapStateToProps)(PrivateRoute);

PublicRoute.js

export const PublicRoute = ({ 
    isAuthenticated, 
    component: Component,
    ...rest
}) => (
    <Route {...rest} component={(props) => (
        isAuthenticated ? (
            <Redirect to="/dashboard" />
        ) : (
            <div class="page">
                <Component {...props} />
            </div>
        )
    )} />
);

const mapStateToProps = (state) => ({
    isAuthenticated: !!state.auth.uid
});

export default connect(mapStateToProps)(PublicRoute);

适用的CSS样式


.page {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

.fade-appear,
.fade-enter {
    opacity: 0;
    z-index: 1;
}

.fade-appear-active,
.fade-enter.fade-enter-active {
    opacity: 1.0;
    transition: opacity 300ms linear 150ms;
}

.fade-exit {
    opacity: 1.0;
}

.fade-exit.fade-exit-active {
    opacity: 0;
    transition: opacity 150ms linear;
}

2 个答案:

答案 0 :(得分:3)

显然,您需要将<Switch>包装在父组件中。

CSSTransition的工作原理是,它将尝试向其子级注入classNames作为道具。这意味着子元素将需要使用这些道具并以classNames的形式传递。因此,您需要将<Switch>包装到另一个组件中,以确保此机制正常工作。

Edit on CodeSandbox

const AppRouter = () => (
  <Router>
    <Route
      render={({ location }) => {
        return (
          <TransitionGroup className="RTG">
            <CSSTransition key={location.key} timeout={600} classNames="fade">
              <div>
                <Switch location={location}>
                  <PublicRoute path="/" component={LoginPage} exact={true} />
                  <PrivateRoute
                    path="/dashboard"
                    component={ExpenseDashboardPage}
                  />
                  <PrivateRoute path="/create" component={AddExpensePage} />
                  <PrivateRoute path="/edit/:id" component={EditExpensePage} />
                  <Route component={NotFoundPage} />
                </Switch>
              </div>
            </CSSTransition>
          </TransitionGroup>
        );
      }}
    />
  </Router>
);

答案 1 :(得分:1)

要使流畅的漂亮的整页过渡变得棘手。

大多数解决方案都是在FutureBuilder<bool>( future: isAuth, builder: (context, snapshot) { if(connectionState == connectionState.done){ if (snapshot.hasData){ if (snapshot.data) return TrueWidget(); else return FalseWidget(); // Or with a one-liner : // return snapshot.data ? TrueWidget() : FalseWidget(); } } if(connectionState == ConnectionState.waiting){ return CircularProgressIndicator(); // Don't forget to return a widget in a builder method } } ) 组件上实现的。

链接方法

在自定义链接组件上定义动画。当用户导航时,将进入下一页,而当前页面将离开。

route

当然,为此,您必须创建自己的链接...

因此,您可以使用执行此操作的软件包,例如react-tiger-transition

演示

demo-gif

(我是作者)