Правильный способ повторной выборки запросов после мутации в проекте React ApolloClient

#javascript #reactjs #graphql #react-apollo #apollo-client

#javascript #reactjs #graphql #react-apollo #apollo-клиент

Вопрос:

Создание приложения, которое позволяет вам регистрироваться и входить в систему пользователя в базе данных. После регистрации / входа в систему приложение перемещает вас к контенту.

Код для процесса авторизации:

 const Auth = ({ handleSetAuthorized }) => {
  const { refetch } = useQuery(CURRENT_USER)
  const { error } = useSelector(({ error }) => error)
  const history = useHistory()
  const dispatch = useDispatch()

  const [signup] = useMutation(SIGN_UP, {
    onCompleted: async (data) => {
      const token = data.signup
      localStorage.setItem("token", token)
      await refetch()
      handleSetAuthorized()
      history.push("/pages/edituser")
    },
    onError: error => dispatch(getError(error))
  })

  const [login] = useMutation(SIGN_IN, {
    onCompleted: async (data) => {
      const token = data.login.token
      localStorage.setItem("token", token)
      await refetch()
      handleSetAuthorized()
      history.push("/pages/process")
    },
    onError: error => dispatch(getError(error))
  })

  const signUp = (values) => {
    signup({
      variables: {
        firstName: values.firstName,
        secondName: values.secondName,
        email: values.email,
        password: values.password,
      }
    })
  }

  const signIn = (values) =>{
    login({
      variables: {
        email: values.email,
        password: values.password,
      }
    })
  }

  const removeError = () => {
    dispatch(cleanError())
  }

  return (
    <>
      <div className="auth">
        <img 
          className="auth__logo"
          src={logo} 
          alt="logo"
        />
        <div className="auth__content">
          <Switch>
            <Route path="/auth/signin" >
              <SignIn onSubmit={signIn} removeError={removeError}/>
            </Route> 
            <Route path="/auth/signup">
              <SignUp onSubmit={signUp} removeError={removeError}/>
            </Route>   
          </Switch>
          {error amp;amp;
            <ErrorMessage className="mistake">
              {error.message}
            </ErrorMessage>
          }
        </div>
      </div>
    </>
  )
}

export default Auth
 

Как вы можете видеть после завершения мутации, мне нужно повторно выполнить выборку моего запроса CURRENT_USER, чтобы понять, кто является текущим пользователем, и переместить пользователя к контенту. Я делаю это здесь:

   const { refetch } = useQuery(CURRENT_USER)

  const [signup] = useMutation(SIGN_UP, {
    onCompleted: async (data) => {
      const token = data.signup
      localStorage.setItem("token", token)
      await refetch()                        // <- HERE!
      handleSetAuthorized()
      history.push("/pages/edituser")
    },
    onError: error => dispatch(getError(error))
  })
 

Код работает, но проблема в том, что я не хочу повторную выборку запроса таким образом: импортируйте сам запрос CURRENT_USER, получите функцию повторной выборки из useQuery hook и используйте ее внутри OnCompleted опции мутации.

ApolloClient предоставляет следующее:

  1. Я могу поместить refetchQueries опцию внутри крючка useMutation для повторной выборки моего запроса CURRENT_USER таким образом:
     const [signup] = useMutation(SIGN_UP, {
     refetchQueries: [{query: CURRENT_USER }],   // <- HERE!
     onCompleted: (data) => {
       const token = data.signup
       localStorage.setItem("token", token)
       handleSetAuthorized()
       history.push("/pages/edituser")
     },
     onError: error => dispatch(getError(error))
     

    })

Этот подход не работает, потому что опция refetchQueries обновляет запрос CURRENT_USER до того, как я получу и помещу токен из результата мутации в localStorage. Таким образом, пользователь не перемещается в содержимое, потому что результат запроса CURRENT_USER пуст, а приложение показывает пользователю ошибку.

  1. Я могу использовать пакет npm ‘refetch-queries’. Он предоставляет возможность повторной выборки запросов Apollo в любом месте по имени и частичным переменным. Идеально подходит для моего случая и выглядит так:
     const [signup] = useMutation(SIGN_UP, {
     onCompleted: (data) => {
       const token = data.signup
       localStorage.setItem("token", token)
       refetchQueries: [{query: CURRENT_USER }],   // <- HERE!
       handleSetAuthorized()
       history.push("/pages/edituser")
     },
     onError: error => dispatch(getError(error))
     

    })

Итак, здесь я использую эту опцию внутри OnCompleted option и после помещения токена в localStorage. В моем случае кажется идеальным, но не работает. Я понятия не имею, почему, он выдает ту же ошибку, которая показывает, что результат запроса CURRENT_USER пуст. Возможно, пакет не поддерживается.

Я хочу повторно выполнить выборку запроса CURRENT_USER после перехода пользователя к контенту и до инициализации содержимого (компонента страниц). Но как это сделать, используя хук useEffect внутри содержимого (компонент Pages) и без метода componentWillMount.

И какова наилучшая практика повторной выборки запросов после мутации в моей ситуации?

Комментарии:

1. вы можете «поймать» и сохранить токен в ссылке… apollographql.com/docs/react/networking /…

2. @xadm, я уже использую это в заголовках типа: authorization: token ? Bearer ${token} : «»

3. при получении, а не в этом направлении