Как отменить/проигнорировать действие в сокращении

Есть ли способ отменить действие или игнорировать его?

Или, вернее, лучший/рекомендуемый способ игнорировать действие?

У меня есть следующий создатель действия, и когда я ввожу недопустимый размер (скажем 'some_string') в создателя действия, помимо получения моего собственного предупреждающего сообщения я также получаю: Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.

import { SET_SELECTED_PHOTOS_SIZE } from './_reducers';

export default (size=0) => {
  if (!isNaN(parseFloat(size))) {
    return {
      type: SET_SELECTED_PHOTOS_SIZE,
      size: size,
    };
  } else {
    app.warn('Size is not defined or not a number');
  }
};

Я обсуждал это в redux -канале в Discord (reactiflux), где одно предложение заключалось в том, чтобы использовать decux-thunk следующим образом:

export default size => dispatch => {
  if (!isNaN(parseFloat(size))) {
    dispatch({
      type: SET_SELECTED_PHOTOS_SIZE,
      size: size,
    });
  } else {
    app.warn('Size is not defined or not a number');
  }
}

Другой вариант - игнорировать действие внутри редуктора. Это делает редуктор "более толстым", потому что тогда у него больше обязанностей, но он использует меньше thunk-действий, что упрощает отладку. Я мог видеть, как ударный шаблон выходит из-под контроля, так как я буду вынужден использовать его почти для каждого действия, делая частичные действия немного больными, если их у них будет много.

Ответ 1

Игнорирование действий в Action Creators - это в основном способ рассматривать их как обработчики команд, а не создатели событий. Когда пользователь нажимает кнопку на свое событие, хотя.

Таким образом, в основном существуют два способа решения проблемы:

  • Условие находится внутри создателя действия и thunk-middleware используется

    const cancelEdit = () => (dispatch, getState) => {
      if (!getState().isSaving) {
        dispatch({type: CANCEL_EDIT});
      }
    }
    
  • Условие находится внутри редуктора и не требуется промежуточное ПО

    function reducer(appState, action) {
      switch(action.type) {
       case: CANCEL_EDIT:
         if (!appState.isSaving) {
           return {...appState, editingRecord: null }
         } else {
           return appState;
         }
       default:
         return appState;
    
      }
    }
    

Я настоятельно рекомендую рассматривать взаимодействие с пользовательским интерфейсом как "События" вместо "Команды", и есть два преимущества:

  • Вся ваша логика домена остается в синхронных чистых редукторах, которые очень легко тестировать. Представьте, что вам нужно написать unit test для этой функции.

    const state = {
      isSaving: true,
      editingRecord: 'FOO'
    };
    
    // State is not changed because Saving is in progress
    assert.deepEqual(
      reducer(state, {type: 'CANCEL_EDIT'}),
      state
    );
    
    // State has been changed because Saving is not in progress anymore
    assert.deepEqual(
      reducer({...state, isSaving: false}),
      {isSaving: false, editingRecord: null}
    );
    

Как вы можете видеть, тест действительно просто, когда вы рассматриваете взаимодействие как событие

  1. Что, если вы решили, что вместо того, чтобы игнорировать действие, скорее всего, вы увидите визуальное указание на то, что действие невозможно? Вам нужно будет отправить другое действие или в основном перестроить его. Однако вы не можете использовать горячую перезагрузку с воспроизведением здесь, потому что логика в создателе действия не воспроизводится повторно. Однако, если логика находится в редукторе, вы можете просто изменить поведение, редуктор будет перезагружен и все события будут воспроизведены. Единственное событие, которое вы отправляете, - это то, что пользователь нажал кнопку, и вы не можете отрицать этот факт. Поэтому, если вы не решительно измените пользовательский интерфейс, вы всегда можете перезагрузить его с помощью повтора.

Когда вы думаете о каком-либо взаимодействии с пользовательским интерфейсом в качестве события, вы получите наилучший опыт повторного воспроизведения, потому что событиям не может быть отказано в том, что они только что произошли.