Как вы можете приостановить анимацию в реагирующей-переходной группе при загрузке исходных данных в компоненты? - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть следующий компонент приложения:

            <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, я получу полную анимацию на обоих компонентах, но компонент истории требует данных с сервера, поэтому анимация применяется к пустому контейнеру.

Как можно приостановить анимациюв компонентах реакционно-переходной группы?У меня Redux, поэтому я могу изменить переменную loading в любом месте моего приложения.Кроме того, я не хочу предварительно загружать все данные в магазине при запуске приложения.

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

Я сделал перегрузку через redux и redux-saga.Возможно, это единственный способ добиться следующего с react-router и react-transition-group, потому что анимация с переключением переходов происходит в любое время, когда запускается метод рендеринга, даже если он возвращает ноль.

Я реализовал следующие действия:

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 будет ожидать завершения предварительной загрузки и после этого прекратит загрузку и перенаправление.Хотя он не будет ждать положительного результата, поэтому предварительные загрузчики должны сами обрабатывать ошибки.

Я надеялся, что смогу избежать сложности с избыточностью с помощью встроенной функции маршрутизатора или библиотеки переходов, но у него нет таких инструментов для остановкипереход.Так что это один из лучших способов добиться перехода с предварительно загруженными данными.

0 голосов
/ 04 декабря 2018

Я бы сделал так, чтобы ваш компонент возвращал значение 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;
  }
}
0 голосов
/ 29 ноября 2018

Так что мои случаи были немного другими, но они могли бы помочь вам придумать решение.

  1. Вы можете легко отложить начальное отображение, добавив блок if (this.state.isloaded == true) вокруг всего вашего маршрутизатора.Начните загрузку, когда ваш компонент монтируется, и когда асинхронный вызов завершится, setState({isloaded: true}).
  2. Вы можете создать свой собственный компонент <Link>, который запускает запрос и только после его завершения меняет местоположение страницы.В то же время вы можете делать любые специальные загрузочные прядильщики.

В основном, удерживайте компоненты маршрутизации и перехода в одной стороне.Я считаю их хрупкими и болезненными в таких случаях.Дайте мне знать, если вам нужны какие-либо подробности или фрагменты.

...