Как дождаться завершения сложного потока действий redux-saga перед рендерингом в next.js? - PullRequest
2 голосов
/ 10 апреля 2019

У меня проблемы с ожиданием завершения "одного потока действий" от начала до конца. Приложение работает как обычно в клиенте, но при работе на стороне сервера оно не заканчивается до конца.

Для пояснения, я правильно использую и "next-redux-wrapper", и "next-redux-saga", так как могу добиться отложенного рендеринга, когда использую более простой поток с sagas.

Я думаю, что ошибка в основном в том, что я вообще понимаю (или нет) эффекты саги.

Часть кода опущена для краткости.

api.saga.js

const makeRequest = ({ body, url, method }) =>
  axios({ method, url: url, data: body });


export function* requestWatcher(action) {
  const { feature } = action.meta;

  try {
    const { data: response } = yield call(makeRequest, action.meta);
    yield put(apiSuccess({ response, feature }));
  } catch (error) {
    yield put(apiError({ error: error, feature }));
  }
}

export default function* apiSaga() {
  yield takeEvery(action => action.type.includes(API_REQUEST), requestWatcher);
}

smallBusiness.saga.js

function* watchApiSuccess(action) {
  yield put(
    setPositions({ positions: action.payload.positions })
  );
  yield put(setLoader({ isLoading: false, feature: SMALL_BUSINESS }));
}

function* watchApiError() {
  yield put(setLoader({ isLoading: false, feature: SMALL_BUSINESS }));
}

function* watchFetchPositions() {
  yield put(
    apiRequest({
      body: null,
      method: 'GET',
      url: SMALL_BUSINESS_URL,
      feature: SMALL_BUSINESS
    })
  );
  yield put(setLoader({ isLoading: true, feature: SMALL_BUSINESS }));
}

export default function* smallBusinessSaga() {
  yield all([
    takeLatest(`${SMALL_BUSINESS} ${API_SUCCESS}`, watchApiSuccess),
    takeLatest(`${SMALL_BUSINESS} ${API_ERROR}`, watchApiError),
    takeLatest(FETCH_POSITIONS, watchFetchPositions)
  ]);
}

rootSaga.js

export default function* rootSaga() {
  yield all([call(smallBusinessSaga), call(apiSaga)]);
}

configureStore.js

store.sagaTask = sagaMiddleware.run(rootSaga);

На стороне клиента вызывается функция «watchApiSuccess», а на стороне сервера - нет. Каждая функция генератора называется серверной, за исключением уже упомянутой.

Когда я упросту поток с помощью кода, приведенного ниже, приложение выполнит предварительный рендеринг на стороне сервера.

function* watchPrefetchPositions() {
  const meta = {
    body: null,
    method: 'GET',
    url: SMALL_BUSINESS_URL,
    feature: SMALL_BUSINESS
  };

  const { data: response } = yield call(makeRequest, meta);
  yield put(setPositions({ positions: response.positions }));
}

export default function* smallBusinessSaga() {
  yield all([
    ...
    takeLatest(PRE_FETCH_POSITIONS, watchPrefetchPositions)
  ]);
}

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

1 Ответ

0 голосов
/ 14 апреля 2019

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

Я приложил пример CodeSandBox, чтобы вы могли увидеть, как он работает, мельком.https://codesandbox.io/embed/2586j3k1p

Вы можете видеть, что загрузка появляется на мгновение, пока данные не будут выбраны.Обратите внимание, что CodeSandBox кэширует этот вызов API, поэтому вы едва заметили загрузку текста после первого щелчка.поведение для этого конкретного типа проблем потока, как вы описали.До выхода React Async Rendering я рекомендую использовать флаги.

Если вам нужны подробности, я рекомендую посмотреть Дэн Абрамов: Beyond React 16 |JSConf Исландия 2018

Удачи

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