Я использую Apollo 2.0 для управления вызовами API GraphQL и для обработки глобального состояния моего реагирующего приложения.
Я пытаюсь создать экран входа в систему, где пользователь вводит свое имя пользователя и пароль.отправленный в мой API для аутентификации, и после успеха я хочу установить глобальное состояние isLoggedIn
на true
.
. Пока я могу установить глобальное состояние с одной мутацией, которая использует@client
декларация, так что это касается только местного государства.У меня есть другая мутация, которая вызывает API-интерфейс graphQL и проверяет имя пользователя / пароль, а затем возвращает ответы об успехе / ошибке.
Я хочу иметь возможность установить isLoggedIn
после завершения или сбоя мутации вызова API.
Мой клиент имеет следующее состояние по умолчанию и распознаватели, установленные так:
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
Затем в моем компоненте Login у меня есть следующие мутации и запросы, которые я передаю как HOC с помощью compose:
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)
})
}
Есть ли лучший способ сделать это, чем этот?Это очень запутанное чувство необходимости перезвонить.Я бы подумал, что смогу отобразить ответ на свой объект кеша через мой распознаватель?