проблема с использованием клиента apollo mutate вне рендера - PullRequest
0 голосов
/ 13 февраля 2020

Я хочу, чтобы пользовательский компонент с именем AuthRoute не только проверял, доступны ли определенные данные в избыточном количестве, но и проверял токен с помощью graphql

, вот что я сделал:

const AuthRoute = ({ component: Component, authUser, ...rest }) => {
  const you_must_go_back_to_login = <Route
    {...rest}
    render={props =>
      (<Redirect to={{
        pathname: '/user/login',
        state: { from: props.location }
      }}
      />)
    }
  />

  const continue_journey = <Route
    {...rest}
    render={props =>
      (<Component {...props} />)
    }
  />

  const [dest, setDest] = useState(you_must_go_back_to_login)
  const [checkThat, setCheckThat] = useState(false)

  useEffect(() => {
    client.mutate({
      mutation: VERIFY_TOKEN_MUTATION,
      variables: { token }
    }).then(result => {
      // setDest(continue_journey)
      setCheckThat(true)
    })
    return () => {
      console.log()
    };
  }, [])

  // if(authUser) {
  if (checkThat) {

    return continue_journey

  } else {
    return you_must_go_back_to_login;
  }
}

вот шаги, которые мне нужно сделать:

  1. выполнить мутирование

  2. setDest для одного из you_must_go_to_login или continue_journey

  3. setCheckThat или что-то в этом роде в true или false, основанные на проверенном токене или нет

  4. возвращать dest в результате

теперь у меня есть эта ошибка:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

ОБНОВЛЕНИЕ

Я изменил свой код на это, но я все еще получаю ту же ошибку

const AuthRoute = ({ component: Component, authUser, ...rest }) => {
  const you_must_go_back_to_login = (<Route
    {...rest}
    render={props =>
      (<Redirect to={{
        pathname: '/user/login',
        state: { from: props.location }
      }}
      />)
    }
  />)

  const continue_journey = (<Route
    {...rest}
    render={props =>
      (<Component {...props} />)
    }
  />)

  // const [dest, setDest] = useState(you_must_go_back_to_login)
  const [checkThat, setCheckThat] = useState(false)

  useEffect(() => {
    let isSubscribed = true

    if (isSubscribed) {
      getToken();
    }

    return () => isSubscribed = false
  }, []);

  const getToken = async (sig) => {
    const data = await mutate(VERIFY_TOKEN_MUTATION, { token })
    console.log(data)
    setCheckThat(true);
    console.log(checkThat)
    return;
  };

  return checkThat ? continue_journey : you_must_go_back_to_login;
}

Ответы [ 2 ]

0 голосов
/ 13 февраля 2020

Ошибка вызвана перенаправлением рендеринга раньше, чем получение данных.

Normlly ... вместо useEffect вы можете использовать простое useQuery и использовать условие loading или !data для рендеринга некоторых <Loading/> для принятия решения о перенаправлении или предоставлении доступа (рендеринг перенаправленного или защищенного содержимого).

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

Я использую django graphql jwt, и проблема в том, что verifytoken для этого является мутацией

Обычно / обычно токен передается по заголовку для запросов, а API возвращает ответ или ошибки (для отсутствующего / просроченного токена). Обычно у вас есть возможность запросить у текущего пользователя подтверждение входа в систему.

... , в этом случае мы хотим использовать мутацию

... вместо client.mutate мы можем использовать хуки - useMutation или лучше Пример API (apollo docs:]) - чтобы получить доступ к loading state до принятия решения

const [verifyToken, { data, loading, error }] = useMutation( VERIFY_TOKEN_MUTATION, variables: { token } );

Проблемы?
- мутации не вызываются в начале - loading не будет истинным с самого начала; возвращенные данные.

Для запуска мутации при запуске мы можем использовать useEffect, для возвращаемых данных мы можем использовать обработчик onCompleted, но мы можем просто использовать data - должен быть неопределенным / обнуляться при запуске, использоваться для условий.

Нечто подобное должно работать (нам не нужно ждать, и т. Д. c. - data, loading, error будут обновлены автоматически):

useEffect(() => {
  verifyToken(); // ariables passed earlier, can be passed here
}, []);

if( !data ) return <Loading />

return data.someSuccessVerifiedField ? continue_journey : you_must_go_back_to_login;
0 голосов
/ 13 февраля 2020

Предупреждение довольно очевидно -

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

Специально для этой части -

Чтобы исправить, отмените все подписки и асинхронные задачи в очистке useEffect функция.

Вы используете useEffect неправильно. Вы не должны помещать свою мутацию внутрь useEffect. Что вы можете сделать, так это - вывести мутацию за пределы useEffect.

const [dest, setDest] = useState(you_must_go_back_to_login)
const [checkThat, setCheckThat] = useState(false)

  client.mutate({
      mutation: VERIFY_TOKEN_MUTATION,
      variables: { token }
    }).then(result => {
      // setDest(continue_journey)
      setCheckThat(true)
    })
    return () => {
      console.log()
    };


  useEffect(() => {
    // if(authUser) {
    if (checkThat) {

      return <continue_journey/>

    } else {
      return <you_must_go_back_to_login/>;
    }
  }, [checkThat])
}

Итак, мутация запустится, затем установите переменную checkThat. И тогда будет запущен useEffect, который вернется на основе значения checkThat

...