Как уловить изменения в хранилище redux после отправки асинхронного действия в redux-saga

В моем компоненте входа я пытаюсь войти в систему нажатием кнопки, затем вызывается соответствующая функция handleLogin. В этой функции я отправляю асинхронную функцию с моими учетными данными пользователя в качестве полезной нагрузки. В моей саге я делаю запрос, помещающий ошибку для сохранения, если в ответе есть такое поле, иначе я установил там пользователя. По умолчанию поле ошибки в магазине - «ложь». В моем компоненте, в котором я отправляю действие, я хочу знать состояние поля ошибки в магазине сразу после успешного / неудачного ответа. Когда я пытаюсь войти в систему с неправильными учетными данными и записывать состояние ошибки в консоль, я сначала получаю «старое» (начальное) значение error: false вместо error: true. Только после второй попытки входа в систему ошибка становится истинной. Есть ли способ узнать фактическое состояние ошибки в магазине сразу после отправки асинхронного действия?

Редуктор:

const initialState = {
  userData: [],
  error: false
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
  case SET_USER:
    return {
      ...state,
      userData: action.payload
    }
  case SET_ERROR:
    return {
      ...state,
      error: action.payload
    }
  default:
    return state;
  }
};

САГАС:

function* handleUserLoad(payload) {
  try {
    const user = yield call(
      loginUser,
      payload
    );
    if(user.data.errors) {
      yield put(setError(true))
    } else {
      yield put(setError(false))
      yield put(setUser(user.data.data.loginUser));
    }
  } catch (error) {
    console.log(error);
  }
}

export default function* userSaga() {
  while (1) {
    const {payload} = yield take(GET_USER);
    yield call(handleUserLoad,payload);
  }
}

ЧАСТЬ КОМПОНЕНТА ЛОГИНА:

const handleLogin = async() => {
    setShouldValidate(true);
    if (allFieldsSet) {
      try {
        loginUser(user)
        // LOGIN ERROR HERE DISPLAYS THE PREVIOUS STATE 'false'
        // INSTEAD OF ACTUAL TRUE AFTER loginUser
        // IF I LOG WITH WRONG CREDENTIALS
        console.log(loginError);
      } catch (e) {
        console.error(e);
      }
    }
  };

person Bobby Fade    schedule 28.06.2020    source источник


Ответы (2)


loginUser(user) в вашем компоненте является асинхронной функцией, поэтому вы не можете ожидать, что console.log(loginError); правильно записывает значение loginError в следующей строке.

Решение:

Во-первых: вы можете привязать свой компонент входа к состоянию ошибки в redux. Как только Saga изменяет состояние на основе успешного / неудачного ответа, ваш компонент входа в систему будет повторно визуализирован. Итак, при рендеринге, если вы откроете console.log, вы можете увидеть, что значение loginError поступает правильно. Таким образом, только в рендере вы можете поместить компонент, который хотите, на основе loginError, который будет отображаться.

Во-вторых: вы можете пропустить использование Saga и напрямую дождаться вашего ответа API входа в систему (вызов API с помощью fetch / axios непосредственно отсюда) в компоненте входа в систему в самом текущем месте. В этом случае вы сможете получить правильный ответ на вход сразу после завершения вызовов ожидания и после этого вы сможете продолжить выполнение своего кода.

person Raghvender Kataria    schedule 28.06.2020

Я внес небольшие изменения в значение ошибки по умолчанию в магазине. Теперь это «ноль» вместо «ложь». Таким образом, я могу проверить, было ли установлено значение false / true в useEffect, и выполнить другую логику.

person Bobby Fade    schedule 28.06.2020