我正在使用Apollo 2.0来管理我的graphQL API调用并处理我的react应用程序的全局状态 .
我正在尝试创建一个登录屏幕,用户输入他们的用户名和密码,这将被发送到我的API进行身份验证,一旦成功,我想将 isLoggedIn
的全局状态设置为 true
.
到目前为止,我能够使用一个使用 @client
声明的突变来设置全局状态,因此它只关注本地状态 . 我有另一个突变,它使graphQL API调用并验证用户名/密码,然后返回成功/错误响应 .
我希望能够在API调用突变完成或失败后设置 isLoggedIn
.
我的客户端具有以下默认状态和解析器设置如下:
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
然后在我的登录组件中,我有以下突变和查询,我在compose的帮助下作为HOC传递:
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
标志的排序?
提前致谢 .
编辑:
我试图在我的变异回调中处理更新状态 .
// Form submission handler
onSubmit = async ({ username, password }) => {
this.setState({loading: true})
this.props.authenticate(username, password)
.then(res => {
this.setState({loading: false})
this.props.updateLoggedInStatus(true)
})
.catch(err => {
this.setState({loading: false, errorMessage: err.message})
console.log('err', err)
})
}
有没有比这更好的方法呢?不得不等待回电感觉非常复杂 . 我原本以为我可以通过我的解析器将响应映射到我的缓存对象?
1 回答
我认为're currently handling it (calling authenticate and then updateLoggedInStatus) is about as clean and simple as you'的方式是
apollo-link-state
. 但是,首先使用apollo-link-state
可能是矫枉过正 . 从Apollo的缓存中导出登录状态可能更简单 . 例如,您可以拥有这样的HOC:请注意,我使用
loggedInUser
作为密钥 . 这意味着我们在配置InMemoryCache
时也必须使用dataIdFromObject
: