Проверьте, существует ли токен ПОСЛЕ отправки формы входа с помощью redux-saga

#react-native #react-redux #redux-saga

Вопрос:

При вызове API я сохраняю свой токен в своей саге о переделке следующим образом:

 export function* onLoginUser(payload) {
  try {
    const response = yield call(loginUserApi, payload.user);
    if (response) {
      yield call(storeToken, response.data.token.api_token);
      yield put(loginUserSuccess(response.data));
    }
  } catch (error) {
    yield put({type: type.LOGIN_USER_ERROR, error});
  }
}

async function storeToken(token) {
  try {
    await AsyncStorage.setItem('token', token);
  } catch (error) {
    console.log('AsyncStorage error during token store:', error);
  }
}
 

На данный момент я считаю, что мне удалось сохранить свой токен в AsyncStorage.

Теперь в моей логинформ. Мне нужно проверить, был ли токен сохранен или существует в AsyncStorage ПОСЛЕ нажатия кнопки «Отправить». Очевидно, что он не будет существовать до тех пор, пока не будет нажата кнопка отправить:

 const dispatch = useDispatch();

  const submitHandler = (val: any) => {
    dispatch(loginUserAction(val));
  };

  onSubmit={values => submitHandler(values)}
 

Теперь я хочу проверить, существует ли он ПОСЛЕ кнопки «Отправить», а затем что-то сделать. Так что я сделал вот что:

 const checkUserSignedIn = async () => {
    try {
      let value = await AsyncStorage.getItem('token');
      if (value != null) {
        navigateTo('HomeScreen');
      }
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    checkUserSignedIn();
  });
 

Однако использование useEffect не будет работать после нажатия кнопки. Как я могу убедиться, что это вызов ПОСЛЕ нажатия кнопки? Правильно ли я это делаю?

Ответ №1:

Есть еще много способов достичь этого. Что я бы вам рекомендовал, так это добавить loading параметр в состояние входа в систему redux.

Таким образом, начальное состояние должно быть примерно таким

 state: {
 ...otherStates,
 loginState: {
  ...yourState,
  loading: false,
  data: null
 }
}
 

Затем вы вызываете свое действие loginUserAction с дополнительным параметром loading: true , который изменяет начальное значение через соответствующий редуктор.

В своей саге вы обновляете свой призыв к успеху следующим образом:

yield put(loginUserSuccess({data: response.data, loading: false}));

Имейте в виду, что блок catch в вашей саге loading: false тоже должен быть, иначе вы можете закончить, loading: true даже когда вызов саги уже завершен. Также не забывайте правильно подключать действия к редукторам.

Наконец, вы хотите использовать крюк селектора для получения обновленных данных в вашем компоненте.

Пример: const { loading, data } = useSelector((state) => state.loginState)

/* You want to store data and get some too so when it changes you actually know if it was updated successfully. Shortly loading: true/false alone is not enough as source of truth */

Теперь ваш компонент будет прослушивать loading и data поддерживать. Чтобы достичь того, чего вы хотите, вы можете просто использовать условие сейчас.

 useEffect(() => {
 if(!loading amp;amp; data !== null) {
  checkUserSignedIn()
 }
}, [loading, data])

 

И последнее, добавьте Throw функцию внутри блока catch storeToken , потому что теперь, если она попадет внутрь блока catch, console.log это не вызовет сбоя в saga call() , и это будет продолжаться yield put(loginUserSuccess(response.data)); , но ваши данные вообще не будут сохранены 🙂