@mix-9

Что должно содаржаться в reducer'e или где хранить функционал?

Доброго времени суток. Приложение реакт натив с редуксом. Есть набор действий. Есть набор редукторов. И есть функция, вызывающая изменения состояния, то есть "действие". Тут вроде все понятно.
код
export const endOrderCreateAction = (dispatch, orderStatus) => {
    return {
        type: END_ORDER_CREATE,
	orderStatus: orderStatus
    }
};
.........
const orderReducer = (state = {data: [], loading: false}, action) => {
	switch(action.type) {
		case END_ORDER_CREATE:
			return {...state, loading: true};
...........
fetch().then(r => dispatch(endOrderCreateAction(dispatch, r)));

Но потом появилась необходимость сделать несколько действий после отработки функции, соответственно изменить несколько раз состояния. В конкретном примере с заказом надо 1) убрать анимацию загрузки 2) вывести сообщение об успехе 3) добавить в список "мои заказы". Это можно сделать в двух местах: редуктор и функция, изменяющая состояние.
во втором случае несколько раз перерисовка.
fetch().then(r => {
dispatch(endOrderCreateAction(dispatch, r));
dispatch(stopLoadingAction(dispatch, r));
....
});

В первом случае получается каша из состояний,
const orderReducer = (state = {data: [], loading: false}, action) => {
	switch(action.type) {
		case END_ORDER_CREATE:
                ..........
const loadingReducer = (state = {data: [], loading: false}, action) => {
	switch(action.type) {
		case END_ORDER_CREATE:
		case END_USER_LOADING:
		case END_SECTION_LOADING:
                ..........
// одно изменение состояния ловят сразу несколько редукторов

либо
const orderReducer = (state = {data: [], loading: false}, action) => {
	switch(action.type) {
		case END_ORDER_CREATE:
                    return {...state, loading: false} 
// собираем итоговый state 
state = {
loading: orderReducer.loading || sectionReducer.loading || userReducer.loading
}

Как правильно сделать?
  • Вопрос задан
  • 159 просмотров
Пригласить эксперта
Ответы на вопрос 1
@DragonSpirit
Mobile Developer
Вообще тут несколько вариантов решения.
Как вариант для начала использовать одно поле loading для стора и вызывать отдельный action перед сетевыми вызовами, например
так
// todo/actions.js
export const getTodos = (dispatch) => () => {
  dispatch({ type: 'GET_TODOS_REQUEST' });
  return fetch('/api/v1/todos')
    .then((todos) => dispatch({ type: 'GET_TODOS_SUCCESS', payload: todos })
    .catch((error) => dispatch({ type: 'GET_TODOS_FAILURE', payload: error, error: true });
};

// todo/reducer.js
const initialState = { todos: [] };
export const todoReducer = (state = initialState, action) => {
  switch(action.type) {
    case 'GET_TODOS_REQUEST': 
      return { ...state, isFetching: true };
    case 'GET_TODOS_SUCCESS': 
      return { ...state, isFetching: false, todos: action.payload };
    case 'GET_TODOS_FAILURE': 
      return { ...state, isFetching: false, errorMessage: action.payload.message };
    default: 
      return state;
  }
};

Чтобы не было кучи перерендеров стоит использовать селекторы в контейнерах.
Если есть несколько одинаковых сущностей, для которых нужны однотипные action'ы, то можно использовать утиный подход
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы