我是Apollo的新手,我缺少了一些东西。我有一个获取当前登录用户的查询,我在页面加载时运行它,它从我的一个顶级组件中执行(同样的一个组件也包含react-router的匹配逻辑)。
export const GET_USER = gql`
query {
me {
id
email
}
}
`
然后在DOM树中嵌套了登录和注销按钮,这两个按钮都会触发突变,从而设置或取消当前用户的会话。 但是... 我如何更新应用顶部的状态?
我读过 本博文 建议将Apollo Hooks包装到其他自定义钩子中。
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文档中建议的解决方案。
我有什么地方做得不对?
它将看起来像下面的东西。重要的部分是,一旦收到响应,突变就会调用更新函数。这就是你手动更新缓存的位置。目标是替换apollo缓存中的 "me "的值。令人满意的部分是,一旦你把这个工作做好了,从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 }
}
在我的应用程序中,我使用 apollo-cache-inmemory
来管理app的状态。我的app是一个单源的真理状态,好像是重头戏。当你想在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>
)
}