диспетчеризация избыточного действия в промежуточном программном обеспечении вызывает неожиданное поведение - PullRequest
0 голосов
/ 08 декабря 2018

Я пытаюсь понять, как работает промежуточное программное обеспечение Redux, во время эксперимента я заметил, что отправка действия из промежуточного программного обеспечения Redux может привести к неожиданному поведению.

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

у нас есть 3 действия:

const setProgress = (progress) => ({ type: SET_UPLOAD_PROGRESS, progress });
const setThumbnail = (thumbnail) => ({ type: SET_THUMBNAIL, thumbnail });
const calculateTotal = () => ({ type: CALCULATE_TOTAL });

Промежуточное программное обеспечение для расчета общего количества:

export const testMiddleware = (store) => (next) => (action) => {
  if (action.type === 'CALCULATE_TOTAL') {
    return next(action);
  }
  const result = next(action);
  store.dispatch(calculateTotal());
  return result;
};

Редуктор:

const initialState = {
  progress: 0,
  total: 0,
  thumbnail: ''
};
export function uploadReducer(state = initialState, action) {
  switch (action.type) {
    case SET_UPLOAD_PROGRESS:
      state.progress = action.progress;
      return { ...state };
    case SET_THUMBNAIL:
      state.thumbnail = action.thumbnail;
      return { ...state };
    case CALCULATE_TOTAL:
      state.total += state.progress * 5;
      return { ...state };
    default:
      return state;
  }
}

здеськод для имитации загрузки файла:

  let cnt = 0;
  // simulate upload progress
  const setNewProgress = () => {
    cnt += 2;
    if (cnt > 5) return;
    setTimeout(() => {
      store.dispatch(setProgress(cnt * 2));
      setNewProgress();
    }, 1000);
  };
  setNewProgress();
  // simulate thumbnail generating
  setTimeout(() => {
    store.dispatch(setThumbnail('blob:http://thumbnail.jpg'));
  }, 2500);

Вот последовательность событий:

первое действие работает как задумано и устанавливает значение прогресса:

enter image description here

проблема начинается здесь;thumbnail предположим, что он установлен с помощью setThumbnail, но devtools показывает, что он был установлен с помощью Calculate, и каждая отправка после этого не соответствует:

enter image description here

Что я здесь не так делаю?это дизайн?как я могу отправить действие в промежуточном программном обеспечении, не вызывая вышеуказанную проблему?

1 Ответ

0 голосов
/ 09 декабря 2018

Это неожиданное поведение может быть вызвано тем, что ваш uploadReducer не является чистым , то есть он напрямую воздействует на ваше состояние (например, state.progress = action.progress;).Редукторы должны только возвращать новое состояние и не изменять существующее состояние, введенное в ваш редуктор с помощью редуктора.следовательно, ваш редуктор должен выглядеть следующим образом:

export function uploadReducer(state = initialState, action) {
  switch (action.type) {
    case SET_UPLOAD_PROGRESS:
      return { ...state, progress: action.progress };
    case SET_THUMBNAIL:
      return { ...state, thumbnail: action.thumbnail };
    case CALCULATE_TOTAL:
      return { ...state, total: state.total + state.progress * 5 };
    default:
      return state;
  }
}

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

Ваше промежуточное программное обеспечение выглядит нормально (выправильно предотвращают рекурсию, а также возвращают результат next() (который не нужен в вашем примере, но все же имеет смысл в реальном приложении). Ваши действия также выглядят хорошо (примечание стиля: вы можете заключить полезную нагрузку вашего действия в payload свойство, которое является общим соглашением ).

...