我该如何将使用Redux-Saga进行长时间操作的React站点迁移到React挂钩?

时间:2019-06-06 15:04:38

标签: javascript reactjs redux redux-saga

有太多的教程都讲着稍微不同的标准和约定,将Redux Saga迁移到React钩子的最佳实践是什么?

1 个答案:

答案 0 :(得分:1)

以下是我正在使用的方法,请预先准备。

Redux商店

动作名称-constants/index.js

export const SET_NARRATIVE = 'SET_NARRATIVE'

动作创建者-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

将Reducer连接到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

通过id请求叙述,并“输入”结果或错误的操作。

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,
  }

将reducer挂接到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-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)
}

将Saga挂接到调度程序中-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