Как мне перенести сайт React, который использует Redux-Saga для длительных операций, на ловушки React? - PullRequest
1 голос
/ 06 июня 2019

Существует так много руководств, проповедующих слегка отличающиеся стандарты и соглашения, какова лучшая практика для переноса Redux Saga на ловушки React?

1 Ответ

1 голос
/ 06 июня 2019

Ниже приводится подход, который я использую, предварительные хуки.

Redux Store

Название действия - constants/index.js

export const SET_NARRATIVE = 'SET_NARRATIVE'

Action Creator - actions/narrative.js

Компоненты вызывают это, чтобы отправить действие

export const setNarrative = narrative => {
  return {
    type: SET_NARRATIVE,
    narrative,
  }
}

Создание этого narrativeSet будет лучше соответствовать соглашению об именах Saga, но не будет так читаемо в компонентах.

Редуктор - reducers/narrative.js

Показывает отправленное действие и применяет обновление от компонента к хранилищу.

export const narrativeReducer = (state = narrativeInitialState, action) => {
  switch (action.type) {
  case SET_NARRATIVE:
    return {
      ...state,
      narrative: action.narrative,
    } ...

Комбинированные редукторы - reducers/index.js

Подключите редуктор к циклу действий / событий Redux

const reducers = combineReducers({
  narrative: narrativeReducer,

Компоненты - components/Draft.js

Подключите компонент к состоянию Redux и диспетчеру. Думаю, лучше всего использовать containers/ для подключенных компонентов, но большинство моих компонентов подключены.

Чтение из this.props.narrative, запись с использованием this.props.setNarrative(narrative).

import { setNarrative } from '../actions/narrative'

const mapStateToProps = state => ({
  narrative: state.narrative.narrative,  // processing here if necessary
})
const mapDispatchToProps = { setNarrative }
Draft = connect(
  mapStateToProps,
  mapDispatchToProps
)(Draft)
export default Draft

Redux Saga

Имена действий - constants/index.js

export const NARRATIVE_FETCH_REQUESTED = 'NARRATIVE_FETCH_REQUESTED'
export const NARRATIVE_FETCH_SUCCEEDED = 'NARRATIVE_FETCH_SUCCEEDED'
export const NARRATIVE_FETCH_FAILED = 'NARRATIVE_FETCH_FAILED'

Создатели действий - actions/narrative.js

Действия, чтобы запросить повествование по идентификатору и «поставить» результат или ошибку.

export const narrativeFetchRequested = id => {
  return {
    type: NARRATIVE_FETCH_REQUESTED,
    id,
  }
}
export const narrativeFetchSucceeded = narrative => {
  return {
    type: NARRATIVE_FETCH_SUCCEEDED,
    narrative,
  }
}
export const narrativeFetchFailed = error => {
  return {
    type: NARRATIVE_FETCH_FAILED,
    error,
  }
}

Пункты редуктора - reducers/narrative.js

Сохранение статуса выборки, результатов и / или ошибок в Redux Store.

case NARRATIVE_FETCH_REQUESTED:
  return {
    ...state,
    narrativeLoading: true,
  }
case SET_NARRATIVE: )  // non-Saga version above
case NARRATIVE_FETCH_SUCCEEDED:
  return {
    ...state,
    narrative: action.narrative,
    narrativeLoading: false,
  }
case NARRATIVE_FETCH_FAILED:
  return {
    ...state,
    narrative: null,
    narrativeLoading: false,
    error: action.error,
  }

Подключите редуктор к циклу действий / событий Redux - reducers/index.js

const reducers = combineReducers({
  narrative: narrativeReducer,  // as above

API уровень - api/index.js

export const getNarrative = id => {
  return axios.get(`${API_URL}narratives/${id}/`)
}

Саги - sagas/narrative.js

Отправьте запрос в API, верните обработанные данные, затем отправьте (поместите) действие для обновления хранилища.

export function* fetchNarrative(action) {
  try {
    const { id } = action
    const { data: narrative } = yield call(getNarrative, id)
    createPermissionShortcuts(narrative)  // some off-thread processing
    narrative.updated_display = renderDate(narrative.updated) // Python backend naming convention
    yield put(fetchNarrativeSucceeded(narrative))
  } catch (error) {
    yield put(fetchNarrativeFailed(error))
  }
}
export function* watchNarrativeRequested() {
  yield takeEvery(NARRATIVE_FETCH_REQUESTED, fetchNarrative)
}

Крюк Сага в диспетчер - sagas/index.js

export default function* rootSaga() {
  yield all([
    watchNarrativeRequested(),
    ...

Бегущая Сага

В containers/App.js для запуска Saga при запуске приложения:

sagaMiddleware.run(fetchNarrative)  // to trigger on app start

.. и / или ..

В components/Section.js для запуска из компонента:

  • Запуск с использованием this.props.fetchNarrativeRequested(id)
  • при загрузке this.props.narrativeLoading === true
  • При загрузке читать с this.props.narrative
  • Если не удалось, прочитайте ошибку от this.props.narrativeError
class Section extends React.Component {
  componentDidMount() { // in your component - render then fetch
    this.props.narrativeFetchRequested(this.props.match.params.id) //if router parse url
  } ...
}
const mapStateToProps = state => {
  return {
    narrative: state.narrative.narrative,
    narrativeLoading: state.narrative.narrativeLoading,
    narrativeError: state.narrative.error,
  }
}
const mapDispatchToProps = {
  narrativeFetchRequested,
}
Section = connect(
  mapStateToProps,
  mapDispatchToProps
)(Section)
export default Section
...