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

Как правильно сделать?
  • Вопрос задан
  • 155 просмотров
Пригласить эксперта
Ответы на вопрос 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'ы, то можно использовать утиный подход
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы