Компоненты маршрута разбиения кода, завернутые в HOC с React Loadable - PullRequest
0 голосов
/ 25 июня 2018

У меня проблемы с использованием React Loadable с разбивкой кода на основе маршрута с использованием Webpack 3.11.

Когда я пытаюсь отобразить свое приложение на сервере, мои асинхронные модули немедленно разрешаются, не ожидая обещания.Таким образом, выход SSR становится <div id="root"></div>.

App.js:

const App = () => (
  <Switch>
    {routes.map((route, index) => (
      <Route key={index} path={route.path} render={routeProps => {
        const RouteComponent = route.component
        return <RouteComponent {...routeProps} />
      }} />
    ))}
  </Switch>
)

Я определил мои асинхронные компоненты маршрута с помощью React Loadable следующим образом:

Маршруты.js

function Loading ({ error }) {
  if (error) {
    return 'Oh nooess!'
  } else {
    return <h3>Loading...</h3>
  }
}

const Article = Loadable({
  loader: () => import(/* webpackChunkName: "Article" */ '../components/contentTypes/Article'),
  loading: Loading
})

const Page = Loadable({
  loader: () => import(/* webpackChunkName: "Page" */ '../components/contentTypes/Page'),
  loading: Loading,
  render (loaded, props) {
    let Component = WithSettings(loaded.default)
    return <Component {...props}/>
  }
})

export default [
  {
    path: `/:projectSlug/:env${getEnvironments()}/article/:articleSlug`,
    component: Article,
    exact: true
  },
  {
    path: `/:projectSlug/:env${getEnvironments()}/:menuSlug?/:pageSlug?`,
    component: Page
  }
]

WithSettings.js

export default (WrappedComponent: any) => {
  class WithSettings extends React.Component<WithSettingsProps, WithSettingsState> {
    static displayName = `WithSettings(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`

    state = {
      renderWidth: 1200
    }

    componentDidMount () {
      this.loadSettings({ match: { params: { projectSlug: '', env: '' } } })
      window.addEventListener('resize', this.onResize)
      this.onResize()
    }

    componentWillUnmount () {
      if (isClient) {
        window.removeEventListener('resize', this.onResize)
      }
    }

    componentDidUpdate (oldProps) {
      this.loadSettings(oldProps)
    }

    onResize = () => {
      this.setState({ renderWidth: this.getLayoutWidth() })
    }

    getLayoutWidth () {
      return (document.body && document.body.offsetWidth) || 0
    }

    loadSettings (oldProps) {
      const { settings, request, getNewSettings } = this.props
      const { projectSlug: oldProjectSlug, env: oldEnv } = oldProps.match.params
      const { projectSlug: newProjectSlug, env: newEnv } = this.props.match.params

      if (
        (
          oldProjectSlug !== newProjectSlug ||
          oldEnv !== newEnv
        ) ||
        (
          settings === undefined ||
          (request.networkStatus === 'ready')
        )
      ) {
        getNewSettings()
      }
    }

    render () {
      const { settings, request, history, location, match } = this.props
      const { renderWidth } = this.state

      if (!settings || !request || request.networkStatus === 'loading') {
        return <div />
      }

      if (request.networkStatus === 'failed') {
        return <ErrorBlock {...getErrorMessages(match.params, 'settings')[4044]} fullscreen match={match} />
      }

      return (
        <WrappedComponent
          settings={settings}
          settingsRequest={request}
          history={history}
          location={location}
          match={match}
          renderWidth={renderWidth}
        />
      )
    }
  }

  hoistNonReactStatic(WithSettings, WrappedComponent)

  return connect(mapStateToProps, mapDispatchToProps)(WithSettings)
}

Мне удалось сузить его до WithSettings HOC, который я использую дляоберните мои компоненты маршрута. Если я не использую WithSettings HOC (как с маршрутом Статьи), тогда мой вывод SSR ждет завершения асинхронного импорта, и сгенерированный сервером html включает разметку, связанную с маршрутом (хорошо!).Если я использую HOC (как с маршрутом страницы), то модуль немедленно разрешается, и мой вывод SSR превращается в <div id="root"></div, потому что он больше не ожидает завершения динамического импорта перед рендерингом.Проблема в том, что мне нужен HOC WithSettings во всех моих маршрутах, так как он получает необходимые данные с сервера, который мне нужен для визуализации приложения.

Может кто-нибудь сказать мне, как я могу использовать HOC и * 1031?* использовать асинхронный компонент React Loadable для компонентов маршрута, чтобы он работал на сервере?

1 Ответ

0 голосов
/ 26 июня 2018

Удалось выяснить это.

Это было из-за моего HOC.В методе рендеринга он вернул бы <div />, когда settings или request, где undefined или request.networkStatus равно loading.Оказывается, это отключило рендеринг на стороне сервера.Удаление этого блока было достаточно, чтобы заставить его работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...