React Router 4 + Разделение кода | Перемонтирование компонентов

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

import React from 'react'
import Loadable from 'react-loadable'
import { Route } from 'react-router-dom'

class App extends React.Component {
    state = {
        kappa: false
    }

    componentDidMount() {
        setTimeout(() => {
            setState({ kappa: true })
        }, 1000)
    }

    render() {
        return (
            <div className="app">
                <Route exact path="/:locale/" component={Loadable({
                    loader: () => import('../views/IndexPage/index.jsx'),
                    loading: () => "loading"
                })} />
                <Route exact path="/:locale/registration" component={Loadable({
                    loader: () => import('../views/Registration/index.jsx'),
                    loading: () => "loading"
                })} />

                {this.state.kappa && <p>Hey, Kappa-Kappa, hey, Kappa-Kappa, hey!</p>}
            </div>
        )
    }
}

Когда состояние обновляется (kappa становится истинным и появляется p), компонент на активном маршруте (неважно какой - IndexPage или Registration) перемонтируется. Если я импортирую компонент вручную в приложение и передаю его в Route без разделения кода, компоненты на маршрутах не перемонтируются (это так очевидно).

Я также пробовал динамический импорт веб-пакета, например:

<Route path="/some-path" component={props => <AsyncView {...props} component="ComponentFolderName" />

где import(`/path/to/${this.props.component}/index.jsx`) работает в componentDidMount и заполняет состояние AsyncView, и ведет себя аналогично ситуации Loadable.

Я полагаю, проблема в том, что component для Route является анонимной функцией

Возникает вопрос: как избежать перемонтирования компонентов маршрута?


person Limbo    schedule 14.02.2018    source источник
comment
Нашел небольшой обходной путь - передать Route какой-нибудь статический компонент (например, AsyncRoute), а затем определить массив маршрутов с именами компонентов и попытаться импортировать с помощью webpack динамического import. Довольно плохое решение в смысле отсутствия динамики, но оно работает   -  person Limbo    schedule 14.02.2018


Ответы (1)


Что ж, такое поведение является нормальным и задокументировано в документации React Router 4:

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

render отлично работает как с React Loader, так и с разделением кода webpack.

person Limbo    schedule 16.02.2018