How return data from a GraphQL mutation? - reactjs

I have the following redux-form below... How can I get the console.log to obtain the user.id from the graphQL mutation result data?
const withForm = compose(
withMySignupMutation,
reduxForm({
...
onSubmit: async (values, dispatch, {
mySignup,
}) => {
try {
const result = await mySignup(values);
console.log('I Need user.id here');
console.log(result.user.id);
...
withMySignupMutation
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
export const SIGNUP_MUTATION = gql`
mutation (
$email: String!
$name: String!
) {
signup(authProvider: {
mySignup: {
email: $email
name: $name
}
}) {
token
}
}
`;
export default graphql(
SIGNUP_MUTATION,
{
props: ({ mutate }) => ({
mySignup: async (variables) => {
const { data } = await mutate({ variables });
},
}),
}
);
Thank you! happy holidays

In my opinion, it should be result.data.signup.id but we need to see the resolvers and your schema definition. It depends on what the resolvers are sends back. It should be a User type.
Anyway, you must ask for the id in your mutation otherwise it won't get resolved:
export const SIGNUP_MUTATION = gql`
mutation (
$email: String!
$name: String!
) {
signup(authProvider: {
mySignup: {
email: $email
name: $name
}
}) {
token
id ### <===HERE===
}
}
`
And if you have a graphiql access to the server:
click on the top-right corner the DOCS button, then
click mutation: Mutation
then you should see something like:
signup(authProvider: AuthProviderNewcomerData!): User
Then you know you will get a User back.

Related

how can I pass arguments to the query method in apollo?

I am using apollo client to fetch the data.
And I want it to only get those todos that are made by the logged in user only.
But this piece doesn't work
Source code:
import { gql } from '#apollo/client';
export const todoService = {
getTodoItems: () => gql`
query todoQuery($loggedUserId: String!) {
todo(where: { userId: { _eq: $loggedUserId } }, order_by: { createdAt: desc }) {
id
todo {
title,
body,
status
}
userId
}
}
}
`
Redux thunk file
import { createAsyncThunk } from '#reduxjs/toolkit';
import { apolloClient } from '#/Apollo';
import { todoService } from './_graphql';
export const todoThunk = {
getTodoItems: createAsyncThunk(`db/getTodoItems`, async (loggedUserId: string) => {
const response = await apolloClient.query({
query: todoService.getTodoItems(),
variables: { loggedUserId },
fetchPolicy: `network-only`,
});
return response;
}),
React Component
useEffect(
dispatch(todoThunk.getTodoItems(loggedUserId));
,[dispatch])
However it works when I hard code the userId in place of variable loggedUserId like this:
export const todoService = {
getTodoItems: () => gql`
query todoQuery {
todo(where: { userId: { _eq: "some_hard_coded_id" } }, order_by: { createdAt: desc }) {
id
todo {
title,
body,
status
}
userId
}
}
}
`
It seems you missed a $ sign
try:
import { gql } from '#apollo/client';
export const todoService = {
getTodoItems: () => gql`
query todoQuery($loggedUserId: String!) {
todo(where: { userId: { _eq: $loggedUserId } }, order_by: { createdAt: desc }) {
id
todo {
title,
body,
status
}
userId
}
}
}
`
this worked for me.
import { gql } from '#apollo/client';
export const todoService = {
getTodoItems: () => gql`
query todoQuery($loggedUserId: uuid! = loggedUserId) {
todo(where: { userId: { _eq: $loggedUserId } }, order_by: { createdAt: desc }) {
id
todo {
title,
body,
status
}
userId
}
}
}
`

Mutation is not a function?

I want to use social login by using graphql.
I want to get accessToken from social login by using kakaologin function and then i use it to make token by using kakakoLoginMutation function.
I try to make const name is access_token(=="123")
and if i success to login by kakao, i get accss_token by authObj. and then i set it to const access_token by using setAccess_token(useState).
console.log(authObj.access_token) show correct strings.
but after setAccess_token(authObj.access_token), console.log(access_token) show "123".
I think that console.log(access_token) have to show not "123" ohter strings.
and the other error is KakaoLoginMutation is not a function.
import { useState } from "react";
import { useMutation } from "react-apollo-hooks";
import { KAKAO_LOGIN, LOCAL_LOG_IN } from "./AuthQuery";
export default () => {
const [access_token, setAccess_token] = useState("123");
const localLogInMutation = useMutation(LOCAL_LOG_IN);
const kakaoLoginMutation = useMutation(KAKAO_LOGIN, {
variables: { provider: "kakao", accessToken: access_token },
});
const kakaoLogin = async (e) => {
e.preventDefault();
window.Kakao.Auth.login({
success: function (authObj) {
setAccess_token(authObj.access_token);
console.log(authObj.access_token);
console.log(access_token);
},
});
const {
data: { socialAuth: token },
} = await kakaoLoginMutation();
console.log(token);
if (token !== "" && token !== undefined) {
localLogInMutation({ variables: { token } });
}
};
return (
<a href="#" onClick={kakaoLogin}>
<h1>카카오로그인</h1>
</a>
);
};
Query.js
import { gql } from "apollo-boost";
export const KAKAO_LOGIN = gql`
mutation SocialAuth($provider: String!, $accessToken: String!) {
socialAuth(provider: $provider, accessToken: $accessToken) {
token
}
}
`;

How does Apollo-Client GraphQL refetchQueries works?

Any idea how do we get the response data from refetchQueries? I got the query response data from mutation.
Mutation
import { gql } from 'apollo-boost';
export const DONE_TASK = gql`
mutation DoneTask($taskId: ID!) {
doneTask(input: {
taskId: $taskId
}) {
task {
id
status
}
}
}
`;
Query
import { gql } from 'apollo-boost';
export const GET_TASKS_BY_STATUS = gql`
query GetTasksByStatus($status: String!) {
getTasksByStatus(status: $status) {
edges {
node {
id
status
description
}
}
}
}
`;
Usage
const response = await client.mutate({
mutation: DONE_TASK,
variables: {
taskId: 1
},
refetchQueries: () => [{
query: GET_TASKS_BY_STATUS,
variables: {
status: "OPEN"
},
}]
});
console.log(response);
Output
data: {
doneTask: {
task: { id: 1, status: 'DONE'}
}
}
But I expect a response data from GET_TASKS_BY_STATUS.
🤔 😕
Any queries you refetch through refetchQueries should already be used by some useQuery hook, Query component or graphql HOC. In order to access the data inside the same component as your mutation, you need to utilize the query being refetched inside that same component:
const { data } = useQuery(GET_TASKS_BY_STATUS, { variables: { status: 'OPEN' } })
const [mutate] = useMutation(DONE_TASK,{
variables: {
taskId: 1,
},
refetchQueries: () => [{
query: GET_TASKS_BY_STATUS,
variables: {
status: 'OPEN',
},
}],
})

this.props.login is not a function react-apollo + compose + graphql

import { graphql, compose } from 'react-apollo'
import gql from 'graphql-tag'
const AUTHENTICATE_USER_MUTATION = gql`
query authenticateUserMutation($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
}
}
`
const LOGGED_IN_USER_QUERY = gql`....`
export default compose(
graphql(AUTHENTICATE_USER_MUTATION, {
name: 'authenticateUserMutation',
options: (props) => ({
variables: { email: props.email,
password: props.password }
})
}),
graphql(LOGGED_IN_USER_QUERY, {
name: 'loggedInUserQuery',
options: { fetchPolicy: 'network-only' }
})
)(withRouter(Login))
After entering email and password on click of login function
OnclickLogin = async () => {
const { email, password } = this.state
await this.props.authenticateUserMutation({variables: {email, password}})
}
It gives error this.props.authenticateUserMutation is not a function.
Well, basically you are firing a query, but call it a mutation.
You have to exchange mutation for query, so that it looks like this:
const AUTHENTICATE_USER_MUTATION = gql`
mutation authenticateUserMutation($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
}
}
`
and on the bottom you do not need the options. You would need them if you would want to fire a query.
export default compose(
graphql(AUTHENTICATE_USER_MUTATION, {
name: 'authenticateUserMutation'
}),

Reuse mutations without duplicating code in Apollo + React?

I have the mutation below in a React Component. Im going to need the same mutation in multiple components and on different pages.
How can I reuse my mutation code without repeating it?
This example isn't that complex but some queries use optimistic UI and write to the store.
import React from 'react';
import { graphql, compose } from 'react-apollo';
import { gql } from 'apollo-boost';
const JoinLocation = props => {
if (props.ME.loading) return null;
const { locationMachineName } = props;
const me = props.ME.me;
const submit = () => {
props
.JOIN_LOCATION({
variables: {
userId: me.id,
locationMachine: locationMachineName,
},
})
.catch(err => {
console.error(err);
});
};
return <button onClick={() => submit()}>Join location</button>;
};
const ME = gql`
query me {
me {
id
}
}
`;
const JOIN_LOCATION = gql`
mutation joinLocation($userId: ID!, $locationId: ID!) {
joinLocation(userId: $userId, locationId: $locationId) {
id
}
}
`;
export default compose(
graphql(JOIN_LOCATION, { name: 'JOIN_LOCATION' }),
graphql(ME, { name: 'ME' }),
)(JoinLocation);
Create a higher-order component (HOC) for the mutation/query that contains the gql options and optimistic UI logic:
const JOIN_LOCATION = gql`
mutation joinLocation($userId: ID!, $locationId: ID!) {
joinLocation(userId: $userId, locationId: $locationId) {
id
}
}
`;
export const withJoinLocation = component => graphql(JOIN_LOCATION, { name: 'JOIN_LOCATION' })(component);
Then wrap your different components with it.
export default withJoinLocation(JoinLocation);
UPDATE: Based on your below comment, if you want to encapsulate the whole submit logic and not just the mutation as stated in your question, you can use a render prop like so:
import React from 'react';
import { graphql, compose } from 'react-apollo';
import { gql } from 'apollo-boost';
const JoinLocation = props => {
if (props.ME.loading) return null;
const { locationMachineName } = props;
const me = props.ME.me;
const submit = () => {
props
.JOIN_LOCATION({
variables: {
userId: me.id,
locationMachine: locationMachineName,
},
})
.catch(err => {
console.error(err);
});
};
return props.render(submit);
};
const ME = gql`
query me {
me {
id
}
}
`;
const JOIN_LOCATION = gql`
mutation joinLocation($userId: ID!, $locationId: ID!) {
joinLocation(userId: $userId, locationId: $locationId) {
id
}
}
`;
export default compose(
graphql(JOIN_LOCATION, { name: 'JOIN_LOCATION' }),
graphql(ME, { name: 'ME' }),
)(JoinLocation);
Now any component can consume the reusable submit logic. Assume you name the above component JoinLocation.js:
import JoinLocation from './JoinLocation';
const Comp = () => {
return <JoinLocation render={submit => <button onClick={() => submit()}>Join location</button>}/>
}

Resources