redux-saga/loadable-component 第一次获取没有等待,但所有接下来的都是

redux-saga/loadable-component first fetch not waited, but all the next ones yes

我无法制作合适的服务器端。

当我启动服务器并进行抓取时 http://localhost:3000/last-movie-releases

toPromise() 没有等待 第一次提取。但是我接下来做的所有其他都很好,服务器端就可以了。

下面只是我的代码片段。我在 class 构造函数中发送我的 redux 动作。 (就像每个人一样)

  store
    .runSaga(rootSaga)
    .toPromise()
    .then(() => {
      console.log('sagas complete');
      const html = ReactDOMServer.renderToString(jsx);
      const css = sheets.toString();
      res.send(
        renderFullPage(html, css, serialize(store.getState()))
      );
    })
    .catch(e => {
      console.log(e.message);
      res.status(500).send(e.message);
    });

  ReactDOMServer.renderToString(jsx);

  store.close();

这是正常行为吗?

PS :我正在谈论的获取数据的传奇从 fork 开始,然后又是 fork,然后是 call。与 real-word repo

中的完全一样

我想知道我是否错过了某个地方 return。

/***********************************************
***************** UPDATE BELOW *****************
***********************************************/

我给你我的传奇(只有 2 个)

import {
  take,
  put,
  call,
  fork,
  select,
  delay,
  all,
  takeEvery,
  takeLatest
} from 'redux-saga/effects';
import * as api from './api';

import * as actions from '../actions';

// each entity defines 3 creators { request, success, failure }
const { movies, movie } = actions;

function* fetchEntity(entity, apiFn, body) {
  yield put(entity.request(body));
  const { response, error } = yield call(apiFn, body);
  if (response) yield put(entity.success(body, response));
  else yield put(entity.failure(body, error));
}

// yeah! we can also bind Generators
export const fetchMovies = fetchEntity.bind(null, movies, api.fetchMovies);
export const fetchMovie = fetchEntity.bind(null, movie, api.fetchMovie);

/******************************************************************************/
/********************************* SAGAS **************************************/
/******************************************************************************/

function* sagaFetchMovies() {
  yield call(fetchMovies);
}
function* sagaFetchMovie(movieId) {
  yield call(fetchMovie, movieId);
}

/******************************************************************************/
/******************************* WATCHERS *************************************/
/******************************************************************************/

function* watchFetchMovies() {
  while (true) {
    yield take(actions.FETCH_MOVIES);
    yield fork(sagaFetchMovies);
  }
}

function* watchFetchMovie() {
  while (true) {
    const { movieId } = yield take(actions.FETCH_MOVIE);
    yield fork(sagaFetchMovie, movieId);
  }
}

export default function* root() {
  yield all([fork(watchFetchMovies), fork(watchFetchMovie)]);
}
/***********************************************
***************** UPDATE BELOW *****************
***********************************************/

我告诉你我在哪里派遣我的行动;)

...
class Movie extends Component {
  constructor(props) {
    super(props);
    this.state = { isSlideShowOpened: false };

    const movie = props.app.movie.results.filter(e => e.id === Number(props.match.params.movieId));

    if (movie.length === 0) {
      props.fetchMovie(props.match.params.movieId); // <---- I dispatch here because componentWillMount is deprecated :s
    }
  }
...
...
class Movies extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {};
    if (props.app.movies.results.length === 0) {
      props.fetchMovies(); // <---- I dispatch here because componentWillMount is deprecated :s
    }
  }
...

@loadable/component 服务器端渲染有一个很大的警告 lol

@loadable/component 强制您为每条路线拆分代码,并最终使用回退(下载 js 包时的旋转器)

让我提醒你 @loadable/component 是市场上唯一能够为服务器端渲染做拆分代码的模块 lol

好吧,none 你的故事将由 @loadable/component 等待。我别无选择,这对 google 和 bing 来说并不是那么糟糕,我认为...

例如,我的 React 路由器看起来像这样

import React from 'react';
import loadable from '@loadable/component';
import Loading from './Exception/Loading';

const Home = loadable(() => import('./Home/index'), { fallback: <Loading /> });
const Movies = loadable(() => import('./Movies/index'), { fallback: <Loading /> });
const Movie = loadable(() => import('./Movie/index'), { fallback: <Loading /> });

const Slide1 = loadable(() => import('./Slides/Slide1'), { fallback: <Loading /> });

const Forbidden = loadable(() => import('./Exception/403'));
const NoMatch = loadable(() => import('./Exception/404'));
const ServerDown = loadable(() => import('./Exception/500'));

const indexRoutes = [
  {
    exact: true,
    path: '/',
    component: Home
  },
  {
    exact: true,
    path: '/last-movie-releases',
    component: Movies
  },
  {
    path: '/movie-details/:movieId/:slideshow?',
    component: Movie
  },
  {
    path: '/slide1',
    component: Slide1
  },
  { path: '/403', component: Forbidden },
  { path: '/404', component: NoMatch },
  { path: '/500', component: ServerDown },
  { name: 'NoMatch', component: NoMatch }
];

export default indexRoutes;