Reputation: 14818
I started using ApolloClient and i must say, the documentation is horrible.
My application will use GraphQL, but the login needs to be done using a simple POST
request to /login
providing the username and password, as formdata.
And man, getting that to work has been a complete nightmare.
Since i have to use apollo-link-rest
i have to first build my client:
import ApolloClient from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloLink } from 'apollo-link'
import { createHttpLink } from 'apollo-link-http'
import { onError } from 'apollo-link-error'
import { RestLink } from 'apollo-link-rest'
const cache = new InMemoryCache()
const httpLink = new createHttpLink({
credentials: 'include',
})
const restLink = new RestLink({
endpoints: {
localhost: {
uri: "http://localhost:8080"
}
},
credentials: 'include'
})
const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error] Message: ${message}, ${path}`)
})
}
if (networkError) {
console.log(
`[Network error ${networkError}] Operation: ${operation.operationName}`
)
}
})
export const client = new ApolloClient({
link: ApolloLink.from([errorLink, restLink, httpLink]),
cache,
})
then i have my query:
const LOGIN_QUERY = gql`
mutation doLogin($username: String!, $password: String!, $formSerializer: any) {
user(input: { username: $username, password: $password})
@rest(
path: "/login"
type: "user"
method: "POST"
endpoint: "localhost"
bodySerializer: $formSerializer
) {
id
name
}
}`
const formSerializer = (data, headers) => {
const formData = new URLSearchParams()
for (let key in data) {
if (data.hasOwnProperty(key)) {
formData.append(key, data[key])
}
}
headers.set('Content-Type', 'application/x-www-form-urlencoded')
return { body: formData, headers }
}
I find it utterly crazy that the documentation doesn't have an example of how you send form data, i had to google a lot until i found out how to do it.
and i execute the query in a login component:
const [doLogin, { data }] = useMutation(LOGIN_QUERY, {
onCompleted: () => {
console.log("Success")
},
onError: () => {
console.log("Poop")
}
})
const handleSubmit = (event) => {
event.preventDefault()
console.log('logging in...')
doLogin({
variables: { username, password, formSerializer },
})
}
the server logs me in, returns a session cookie, and a body containing:
{
"data": {
"user": {
"id": 1
"name": "Foobar"
}
}
}
When i check the cache state using the ApolloClient google chrome plugin, the cache has:
user:null
id: null
name: null
so here are my questions:
data
object, even for rest queries?formSerializer
be passed as a variable to the query, because i find that super ugly.As said before... the ApolloClient documentation is one of the worst documentations i have ever read. Not user friendly at all.
Upvotes: 0
Views: 2233
Reputation: 8489
According to Response transforming, apollo expects response from REST APIs like the following:
{
"id": 1,
"name": "Apollo"
}
If you cannot control backend, you can use customized response transformer:
responseTransformer: async response => response.json().then(({data}) => data.data?.user)
Upvotes: 1