Как использовать функцию asyn c внутри setState и иметь возможность отменить до последнего состояния - PullRequest
0 голосов
/ 09 июля 2020

Мне нужно всегда менять состояние переключателя с отмеченного на неотмеченное или наоборот, но после каждого действия мне нужно делать запрос на обновление состояния с помощью API, но если запрос не выполняется, я должен вернуться к предыдущему значение переключения. Я пробовал выполнять операцию внутри setState, и она работает, если нет нескольких параллельных операций, и эта параллельная операция возвращает некоторую ошибку.

Я уже пробовал использовать useEffect, но у меня возникла проблема с генерацией бесконечного l oop, потому что переменная, которая активирует useEffect, также совпадает с той, которую мне нужно вернуться к последнему значению, и это генерирует бесконечное l oop. Кроме того, мне нужно избегать вызова api, когда состояние имеет начальное значение ([]) или когда первый вызов setState исходит из выборки данных из API в первый раз (выборка componentDidMount).

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

Вот изображение того, что я ожидал:

введите описание изображения здесь

Вот часть кода, который я пробовал и работает в некоторых случаях:

interface Option {
  key: string
  pushNotificationTypeData: PushNotificationTypeData
  name: string
  checked: boolean
  onValueChange: () => void
}


const CustomizeNotificationsScreen: React.FunctionComponent<BaseNavigationProps> = ({
  navigation,
}) => {
  const [options, setOptions] = React.useState<Option[]>([])

  const handleSwitchChange = (key: string) => {
    setOptions((prev) => {
      const newOptions = cloneDeep(prev)
      const optionToChangeIndex = newOptions.findIndex((e) => e.key === key)
      newOptions[optionToChangeIndex].checked = !newOptions[optionToChangeIndex].checked

      updateNotificationPermissionsService.execute({
        pushInterval: [{
          type: newOptions[optionToChange].pushNotificationTypeData,
          interval: newOptions[optionToChange].checked
            ? PushNotificationIntervalData.EVER
            : PushNotificationIntervalData.NEVER
        }]
      }).catch(() => {
        showErrorMessage()
        setOptions(prev) // Undo to the the latest change
      })
      return newOptions // Update the options state while the request is being made
    })
  }
...