我正在使用Apollo 2.0来管理我的graphQL API调用并处理我的反应应用程序的全局状态。
我正在尝试创建一个用户输入用户名和密码的登录屏幕,这会被发送到我的API进行身份验证,一旦成功,我想将全局状态isLoggedIn
设置为{{1 }}
到目前为止,我能够使用一个使用true
声明的突变来设置全局状态,因此它只关注本地状态。我有另一个突变,它使graphQL API调用并验证用户名/密码,然后返回成功/错误响应。
一旦API调用变异完成或失败,我希望能够设置@client
。
我的客户端具有以下默认状态和解析器设置如下:
isLoggedIn
然后在我的Login组件中,我有以下突变和查询,我在compose的帮助下作为HOC传递:
const httpLink = new HttpLink({
uri: '/graphql',
credentials: 'same-origin'
});
const cache = new InMemoryCache();
const stateLink = withClientState({
cache,
resolvers: {
Mutation: {
updateLoggedInStatus: (_, { isLoggedIn }, { cache }) => {
const data = {
loggedInStatus: {
__typename: 'LoggedInStatus',
isLoggedIn
},
};
cache.writeData({ data });
return null;
},
},
},
defaults: {
loggedInStatus: {
__typename: 'LoggedInStatus',
isLoggedIn: false,
},
},
});
const link = ApolloLink.from([stateLink, httpLink])
const client = new ApolloClient({
link,
cache
});
export default client
因此,您可以看到我在提交登录表单时使用了const UPDATE_LOGGED_IN_STATUS = gql`
mutation updateLoggedInStatus($isLoggedIn: Boolean) {
updateLoggedInStatus(isLoggedIn: $isLoggedIn) @client
}`
const AUTHENTICATE = gql`
mutation authenticate($username: String!, $password: String!) {
auth(username: $username, password: $password) {
username
sales_channel
full_name
roles
}
}`
const GET_AUTH_STATUS = gql`
query {
loggedInStatus @client {
isLoggedIn
}
}`
export default compose(
graphql(GET_AUTH_STATUS, {
props: ({ data: { loading, error, loggedInStatus } }) => {
if (loading) {
return { loading };
}
if (error) {
return { error };
}
return {
loading: false,
loggedInStatus
};
},
}),
graphql(UPDATE_LOGGED_IN_STATUS, {
props: ({ mutate }) => ({
updateLoggedInStatus: isLoggedIn => mutate({ variables: { isLoggedIn } }),
}),
}),
graphql(AUTHENTICATE, {
props: ({ mutate }) => ({
authenticate: (username, password) => mutate({ variables: { username, password } }),
}),
})
)(withRouter(Login));
。
然后我有this.props.authenticate(username, password)
我可以更新客户端缓存/状态。
如何合并这些内容,以便我可以致电this.props.updateLoggedInStatus(Boolean)
,如果成功,请设置authenticate()
,如果失败,请设置loggedInStatus
或hasErrored
排序
提前致谢。
编辑:
我试图在我的变异回调中处理更新状态。
errorMessage
有没有比这更好的方法呢?感到非常困惑,不得不等待回电。我原本以为我可以通过我的解析器将响应映射到我的缓存对象?
答案 0 :(得分:1)
我认为你当前处理它的方式(调用authenticate然后updateLoggedInStatus)就像你要使用apollo-link-state
一样干净简单。但是,首先使用apollo-link-state
可能是矫枉过正。从Apollo的缓存中导出登录状态可能更简单。例如,您可以拥有这样的HOC:
import client from '../wherever/client'
const withLoggedInUser = (Component) => {
const user = client.readFragment({
id: 'loggedInUser',
fragment: gql`
fragment loggedInUser on User { # or whatever your type is called
username
sales_channel
full_name
roles
# be careful about what fields you list here -- even if the User
# is in the cache, missing fields will result in an error being thrown
}
`
})
const isLoggedIn = !!user
return (props) => <Component {...props} user={user} isLoggedIn={isLoggedIn}/>
}
请注意,我使用loggedInUser
作为密钥。这意味着我们还必须在配置dataIdFromObject
时使用InMemoryCache
:
import { InMemoryCache, defaultDataIdFromObject } from 'apollo-cache-inmemory'
const cache = new InMemoryCache({
dataIdFromObject: object => {
switch (object.__typename) {
case 'User': return 'loggedInUser'
// other types you don't want the default behavior for
default: return defaultDataIdFromObject(object);
}
}
})