8

我有以下应用程序组件:

            <Route render={( { location } ) => (
                <TransitionGroup component="div" className="content">
                    <CSSTransition key={location.key} classNames="slide" timeout={{
                        enter: 1000,
                        exit: 300
                    }} appear>
                        <Switch location={location}>
                            <Route exact path='/' component={Intro}/>
                            <Route path="/history" component={History}/>
                            <Route path="/rules" component={Rules}/>
                            <Route path="/faq" component={Faq}/>
                            <Route path="/feedback" component={Feedback}/>
                            <Route path="/partners" component={Partners}/>
                        </Switch>
                    </CSSTransition>
                </TransitionGroup>
            )}/>

它工作正常,但每个动画都会立即执行。例如,如果我从/rules/history,我在两个组件上都获得了完整的动画,但历史组件需要来自服务器的数据,因此动画应用于空容器。

如何在 react-transition-group 组件中暂停动画?我有 Redux,所以我可以loading在我的应用程序的任何地方更改变量。另外,我不想在应用启动时预加载商店中的所有数据。

4

3 回答 3

2

我会让你的组件在加载时返回 null 并让加载状态确定 CSSTransition 键,如<CSSTransition key={location.key+loading?'-loading':''}

在此处查看示例:https ://stackblitz.com/edit/react-anim-route-once

请注意,要使这项工作不重复,我必须使组件复制加载道具并将其保持在状态中,以便组件的副本之一永远不会显示(这将创建组件的重复,如此处所示:https: //stackblitz.com/edit/react-anim-route-twice )

    <Route render={({ location }) => (
      <TransitionGroup component="div" className="content">
        <CSSTransition key={location.key+(this.state.loading?'-loading':'-loaded')} classNames="crossFade" timeout={{
          enter: 3000,
          exit: 3000
        }} appear>
          <Switch location={location} >
            <Route exact path='/' component={Hello} />
            <Route exact path='/history' render={() =>
              <Delayed setLoading={this.handleSetLoading} loading={this.state.loading} />} />

          </Switch>

        </CSSTransition>
      </TransitionGroup>
    )} />

在组件中是这样的:

export default class History extends React.Component {
  state={loading:this.props.loading}
  componentDidMount() {
    setTimeout(() => {
      this.props.setLoading(false);
    }, 2000);
  }
  render() {
    return !this.state.loading ? <div><h1>History! <Link to="/">Home</Link></h1></div> : null;
  }
}
于 2018-12-04T18:21:12.450 回答
1

所以我的案例有点不同,但它们可能会帮助你想出一个解决方案。

  1. if (this.state.isloaded == true)您可以通过在整个路由器周围添加一个块来轻松延迟初始显示。当你的组件挂载时开始加载,当异步调用完成时,setState({isloaded: true}).
  2. 您可以制作自己的<Link>组件,该组件会启动请求,并且只有在完成后才会更改页面位置。同时,您可以做任何您喜欢的特殊加载微调器。

基本上,将路由和转换组件保持在一侧。我发现它们在这样的情况下变得脆弱和痛苦。如果您需要更多详细信息或片段,请告诉我。

于 2018-11-29T01:44:28.907 回答
0

我已经完成了 peloadingreduxredux-saga. react-router也许这是使用and实现跟随的一种也是唯一的方法react-transition-group,因为在渲染方法运行时随时转换切换动画,即使它返回 null。

我已经实施了以下操作:

const LoadingActions = {
    START_LOADING: 'START_LOADING',
    STOP_LOADING: 'STOP_LOADING',
    REDIRECT: 'REDIRECT',

    startLoading: () => ({
        type: LoadingActions.START_LOADING
    }),

    stopLoading: () => ({
        type: LoadingActions.STOP_LOADING
    }),

    redirect: ( url, token ) => ({
        type: LoadingActions.REDIRECT,
        payload: {
            url,
            token
        }
    })
};

export default LoadingActions;

在减速器中,我实现了简单的加载器减速器,它将打开和关闭加载变量:

import { LoadingActions } from "../actions";

const INITIAL_STATE = {
    loading: false
};

export default function ( state = INITIAL_STATE, { type } ) {
    switch ( type ) {
        case LoadingActions.START_LOADING:
            return { loading: true };
        case LoadingActions.STOP_LOADING:
            return { loading: false };
        default:
            return state;
    }
}

最烦人的就是减速链—— this.props.loader.loading。对于这么简单的事情来说太复杂了。

import { combineReducers } from "redux";
...
import LoadingReducer from './LoadingReducer';

export default combineReducers( {
    ...
    loader: LoadingReducer
} );

大部分工作都在传奇中进行:

function* redirect ( action ) {
    yield put( LoadingActions.startLoading() );
    const { url } = action.payload;

    switch ( url ) {
        case MENU_URL.EXCHANGE:
            yield call( getExchangeData, action );
            break;
        ... other urls...
    }
    yield put( LoadingActions.stopLoading() );
    BrowserHistory.push( url );
}

... loaders ...


function* watchRedirect () {
    yield takeLatest( LoadingActions.REDIRECT, redirect );
}

const sagas = all( [
    ...
    fork( watchRedirect )
] );

export default sagas;

我把监听器放在重定向动作上,所以它会调用重定向生成器。它将开始加载并调用数据预加载yield call将等待预加载完成,然后停止加载并重定向。虽然它不会等待肯定的结果,但预加载器应该自己处理错误。

我希望我可以通过路由器或转换库的内置特性来避免 redux 的复杂性,但它没有这样的工具来停止转换。因此,它是使用预加载数据实现过渡的最佳方式之一。

于 2018-12-04T09:46:33.113 回答