React Router + анимация страницы + модульность - PullRequest
0 голосов
/ 21 января 2019

Это вопрос о маршрутизаторе React и его дизайне, особенно при рассмотрении переходов страниц.

React разработан для модульности, и он превосходен в этой области.Но я нашел одну задачу, которая кажется довольно трудной для выполнения при сохранении изоляции и модульности между компонентами: переходы страниц.

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


Итак, давайте рассмотрим сайт с тремя страницами, PageA, PageB и PageC:

Если мы хотим использовать одинаковую анимацию для монтирования / размонтирования этих трех страниц , скажем, FadeIn для монтирования и FadeOut для размонтирования, тогда мы можем использовать компонент React Transition Group *1013*, чтобы обернуть наш <Switch> компонент, и он будет отвечать за анимацию страниц с помощью CSS-переходов.,Здесь CSS-переходы будут управляться компонентом <CSSTransition> с классом, переданным ClassNames.

<div className="Main">
    <TransitionGroup component={null}>
        <CSSTransition
            key={locationKey}
            appear={true}
            classNames="Main"
            timeout={{
                enter: 300,
                exit: 300,
            }}
        >
            <Switch location={this.props.location}>
                <Route
                    path="/PageA"
                    render={(props) => {
                        return <PageA />;
                    }}
                />
                <Route
                    path="/PageB"
                    render={(props) => {
                        return <PageA />;
                    }}
                />
                <Route
                    path="/PageC"
                    render={(props) => {
                        return <PageA />;
                    }}
                />
            </Switch>
        </CSSTransition>
    </TransitionGroup>
</div>

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

Теперь мы хотим сделать разные переходы для каждого действия монтирования / размонтирования для каждой страницы : PageA монтировать с помощью FadeIn и размонтировать с помощью FadeOut, монтировать PageB с помощью ползунка слева направои размонтируйте, двигая обратно влево, и PageC, чтобы монтировать снизу вверх, и размонтируйте, скользя назад, вниз.

Мы столкнемся с двумя проблемами: если мы используем компонент <CSSTransition>, нам придется пропустить другой classNames опора на него в зависимости от отображаемой страницы.Я еще ничего не реализовал с этой стратегией, потому что есть еще одна проблема, которая касается меня: если мы пойдем по этому пути, мы будем хранить логику для анимации наших компонентов страницы внутри компонента <CSSTransition>, а это за пределами страниц.Это не выглядит очень модульным и изолированным для меня, и чем больше книг я читаю о разработке программного обеспечения, модульности и изоляции, тем больше я запутываюсь в этом подходе.

В идеальном мире логика для анимации страницдолжны быть определены в главном компоненте каждой страницы.Что-то вроде:

class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            classForAnimation: '',
        };
    }

    componentDidMount() {
        this.setState({
            classForAnimation: ' FadeIn',
        });
    }

    render() {
        return <div className={'Home' + this.state.classForAnimation}>
                   I'm Home page
               </div>;
    }
}

export default Home;

И немного CSS:

.Home {
    opacity: 0;
    transition: opacity 0.5s ease;
}

.FadeIn {
    opacity: 1;
}

Это только для монтажа, очень просто.Итак, если это лучшее решение, почему мы его не используем?

Причина в том, что React-маршрутизатор не знает о наших переходах и размонтирует страницу для немедленной анимации, даже не дожидаясь запуска анимации - и, конечно же, ее завершения.- .Это то, что делает компонент <CSSTransition>, но концентрируя логику переходов страниц за пределы компонентов страницы.

Итак, учитывая несколько страниц с различными анимациями при монтировании / демонтировании, вот мои вопросы:

  • A) Есть ли причина, по которой логика переходов между страницами не должна храниться внутри основного компонента каждой страницы?

  • B) Есть ли какая-то причина, по которой React-router были разработаны для размонтирования компонентов, игнорируя случай ожидания различных типов событий на разных страницах?

  • C) Существует ли общий подход для решения этой проблемы?вопрос, который я не рассматриваю?

  • D) Написание нестандартного реагирующего маршрутизатора с нуля будет вариант?

Nik.

1 Ответ

0 голосов
/ 21 января 2019

Здесь вы можете использовать компонент Link, который позволит вам управлять жизненным циклом:

https://yeutech -lab.github.io / реагировать маршрутизаторы-РОМ Utils / # ссылку

Установка:

npm install @yeutech-lab/react-router-dom-utils --save

Использование:

export default (
  <Link
   component={(props) => <div {...props}>Hello world</div>}
   waitChunk={true}
   // You can pass routes as props if you use waitChunk
   routes={[{ name: 'Home', component: Home, path: '/' }]}
   // OR a ContextConsumer that own it
   ContextConsumer={AppContextConsumer}
   // use lifecycle callbacks
   onClick={actionStartLoadingIndicator}
   onPreload={() => console.log(`
     chunk load in the background on mouseover or
     when user click if waitChunk is true
   `)}
   onLoaded={actionStopLoadingIndicator}
   // use delay function so you can animate what you want
   delay={() => Math.random() * 1000}
  />
);

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

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

Вы даже можете использовать блок предварительной загрузки, когда браузер не используется с веб-пакетом.

Поддерживается переход на страницу, вы даже можете управлять индикатором верхней загрузки для перехода на страницу.

У меня была та же проблема, и мне нужно было больше гибкости, поэтому я сделал это.

Редактировать

О ваших 4 вопросах:

A) Есть ли причина, по которой логика переходов между страницами не должна храниться внутри основного компонента каждой страницы?

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

Если вам нужен переход, несмотря ни на что, ваша предыдущая страница уже будет размонтирована.

B) Есть ли какая-то причина, по которой React-router был разработан для размонтирования компонентов, игнорируя случай ожидания различных типов событий на разных страницах?

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

Это очень хорошо.

C) Есть ли общий подход к решению этой проблемы, который я не рассматриваю?

Да, вы должны использовать withRouter и управлять переходом с помощью этого API.

D) Можно было бы написать собственный реагирующий маршрутизатор с нуля?

Это звучит как отличная идея, если вы считаете, что реагирующий маршрутизатор не помогает в вашем случае. Пожалуйста, поделитесь своей работой на GitHub, когда это будет сделано.

Лучший

...