Как обновить локальное состояние после выполнения нескольких запросов и мутаций Apollo? - PullRequest
2 голосов
/ 27 мая 2020

Я новичок в Apollo, и мне что-то не хватает. У меня есть запрос на получение текущего зарегистрированного пользователя, которого я запускаю при загрузке страницы, и он выполняется из одного из моих самых главных компонентов (того же самого, который содержит также соответствующие logi c для response-router):

export const GET_USER = gql`
  query {
    me {
      id
      email
    }
  }
`

Затем, очень вложенные в дерево DOM, у меня есть кнопки входа и выхода, обе из которых запускают мутации, которые будут устанавливать или отменять сеанс для текущего пользователя. Но ... как мне обновить состояние в верхней части приложения на этом этапе?

Я прочитал это сообщение в блоге , в котором предлагается обернуть хуки Apollo в другие пользовательские хуки:

const useAuth = () => {
  const { data: getUserData } = useQuery(GET_USER)
  const [login, { data: loginData } = useMutation(LOGIN)
  const [logout, { data: logoutData } = useMutation(LOGOUT)

  // Should I find out here if I have a user id or not?
  // It's doable, but not clean

  return { login, logout, userId }
}

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

Что я не понимаю?

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Это будет выглядеть примерно так, как показано ниже. Важная часть состоит в том, что мутация вызывает функцию обновления после получения ответа. Это место, где вы вручную обновляете кеш. Цель состоит в том, чтобы заменить значение «я», которое находится в кеше apollo. Удовлетворительно то, что как только вы это заработаете, данные, полученные из useQuery, будут автоматически обновляться (отсюда и повторная отрисовка компонентов с помощью этого хука). Вот ссылка на документацию .

const useAuth = () => {
  const { data: getUserData } = useQuery(GET_USER)
  const [mutateLogin] = useMutation(LOGIN)
  const [mutateLogout] = useMutation(LOGOUT)

  function login(..args) {
    mutateLogin({
      variables: args,
      update(proxy, {data}) {
        proxy.writeQuery({
          query: GET_USER,
          data: {
            me: (GET USER FROM data)
          }
        })
      }
    })
  }

  function logout() {
     mutateLogout({
       update(proxy, {data}) {
         proxy.writeQuery({
           query: GET_USER,
           data: {
             me: null
           }
         });
       }
     })
  }

  return { login, logout, userId }
}
0 голосов
/ 27 мая 2020

В моем приложении я использую apollo-cache-inmemory для управления состоянием приложения. Мое приложение - единственный источник состояния истины, похоже на редукцию. Когда вы хотите манипулировать данными в состоянии Apollo, вы должны использовать useQuery для запроса данных клиента, используйте useMutation для обновления состояния Apollo. Вы можете узнать больше о том, как взаимодействовать с кэшированными данными в Apollo здесь . Это пример:
В client.js:

import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { ApolloClient } from 'apollo-client';

const client = new ApolloClient({
  link: new HttpLink(),
  cache: new InMemoryCache(),
  resolvers: {
    Mutation: {
      setSearchText : (_, { searchValue }, {cache}) => {
        cache.writeData({
          data: {
            searchText: searchValue,
          },
	    })
      }
    }
  }
});

const initialState = {
  searchText: ''
}

cache.writeData({ data: initialState})

В SearchBox.js

import React from 'react'
import { useQuery, useMutation } from '@apollo/react-hooks'
import gql from 'graphql-tag'

const SET_SEARCH_TEXT = gql`
	mutation SetSearchText($searchValue: String!) {
		setSearchText(searchValue: $searchValue) @client
	}
`

const GET_SEARCH_TEXT = gql`
	query SearchText {
		searchText @client
	}
`

const SearchBox = () => {
  const { data: searchTextData, loading, error } = useQuery(GET_SEARCH_TEXT)
  const [setSearchText] = useMutation(SET_SEARCH_TEXT)
  const [value, setValue] = React.useState(searchTextData.searchText || '')
  
  handleChange = (e) => {
    setValue(e.target.value)
  }
  
  onSubmit = () => {
    setSearchText({variables: { searchValue: value }}).then(data => console.log(data))
  }
  return (
    <div>
      <input type="text" value={value} onChange={handleChange} />
      <button onClick={onSubmit}>Submit</button>
    </div>
  )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...