Ниже приводится подход, который я использую, предварительные хуки.
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