Apollo GraphQL query refetch - graphql

I'm trying to do a query refetch after a form submission using Apollo. I am trying to use this example: https://www.apollographql.com/docs/react/data/queries/#refetching
My query is:
const { data: accountData, loading: accountLoading, refetch: accountDataRefetch } = useGetUserSocialLoginQuery({ variables: { accountId: nrId } })
After the form submission I'm calling the refetch function:
const formSubmissionFunction = async () => {
// update an UserSocialLogin entity
await accountDataRefetch()
}
I've also tried to update the query result within the update mutation, but also without success. The UserSocialLogin entity is updated but the data object remains the same. The UI should display the new data.
Do you have any ideas?

Related

using rtk query, how to pull this data from another view

I am trying to understand functionality with Redux toolkit and RTK Query.
I have a functioning query in one view. My question is how do I pull this information in another view?
this is how I launch the query in view #1
const Sidebar = () => {
const { data: clients = [], isFetching: clientsFetching } =
useGetClientsQuery("x#x.com");
this is my single api slice object
//define our single api slice object
export const tradesApi = createApi({
//the cache reducer expects to be added at 'state.api' (already default - this is optional)
reducerPath: "tradesApi",
//all of our requests will have urls starting with '/fakeApi'
baseQuery: fetchBaseQuery({ baseUrl: "https://localhost:44304/api/" }),
//the 'endpoints' represent operations and requests for this server
endpoints: (builder) => ({
//the 'getposts' endpoint is a "query" operation that returns data
getClients: builder.query<ClientData[], string>({
query: (username) => `/dashboard/returnClients?username=${username}`,
}),
getTradeDetail: builder.query<TradeData, number>({
query: (id) => `/dashboard/returnTest?id=${id}`,
}),
}),
});
export const { useGetTradesQuery, useGetClientsQuery, useGetTradeDetailQuery } =
tradesApi;
when I am in view #2, how do I pull this information without querying the api again? I simply want to grab it from the store.
thank you!
You just call useGetClientsQuery("x#x.com"); in the other component. It won't make another request, but just pull the data from the store.

Apollo useQuery() - "refetch" is ignored if the response is the same

I am trying to use Apollo-client to pull my users info and stuck with this problem:
I have this Container component responsible for pulling the user's data (not authentication) once it is rendered. User may be logged in or not, the query returns either viewer = null or viewer = {...usersProps}.
Container makes the request const { data, refetch } = useQuery<Viewer>(VIEWER);, successfully receives the response and saves it in the data property that I use to read .viewer from and set it as my current user.
Then the user can log-out, once they do that I clear the Container's user property setUser(undefined) (not showed in the code below, not important).
The problem occurred when I try to re-login: Call of refetch triggers the graphql http request but since it returns the same data that was returned during the previous initial login - useQuery() ignores it and does not update data. Well, technically there could not be an update, the data is the same. So my code setUser(viewer); does not getting executed for second time and user stucks on the login page.
const { data, refetch } = useQuery<Viewer>(VIEWER);
const viewer = data && data.viewer;
useEffect(() => {
if (viewer) {
setUser(viewer);
}
}, [ viewer ]);
That query with the same response ignore almost makes sense, so I tried different approach, with callbacks:
const { refetch } = useQuery<Viewer>(VIEWER, {
onCompleted: data => {
if (data.viewer) {
setUser(data.viewer);
}
}
});
Here I would totally expect Apollo to call the onCompleted callback, with the same data or not... but it does not do that. So I am kinda stuck with this - how do I make Apollo to react on my query's refetch so I could re-populate user in my Container's state?
This is a scenario where apollo's caches come handy.
Client
import { resolvers, typeDefs } from './resolvers';
let cache = new InMemoryCache()
const client = new ApolloClient({
cache,
link: new HttpLink({
uri: 'http://localhost:4000/graphql',
headers: {
authorization: localStorage.getItem('token'),
},
}),
typeDefs,
resolvers,
});
cache.writeData({
data: {
isLoggedIn: !!localStorage.getItem('token'),
cartItems: [],
},
})
LoginPage
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn #client
}
`;
function IsLoggedIn() {
const { data } = useQuery(IS_LOGGED_IN);
return data.isLoggedIn ? <Pages /> : <Login />;
}
onLogin
function Login() {
const { data, refetch } = useQuery(LOGIN_QUERY);
let viewer = data && data.viewer
if (viewer){
localStorage.setItem('token',viewer.token)
}
// rest of the stuff
}
onLogout
onLogout={() => {
client.writeData({ data: { isLoggedIn: false } });
localStorage.clear();
}}
For more information regarding management of local state. Check this out.
Hope this helps!

How to define client side schema in `react-apollo` application?

I am using react-apollo in my react applicant and I can't figure out how to implement a client side schema.
I have below type definition:
export const alertTypeDefs = gql`
type Query {
alert: Alert
}
type Alert {
message: String!
type: String!
duration: Int!
}
`;
It defines a Query which returns an alert object.
Below is the code I want to use this query.
const cache = new InMemoryCache();
export const createClient = () => {
return new ApolloClient({
cache,
typeDefs: [alertTypeDefs]
});
};
First I initialised a ApolloClient instance with memory cache and alertTypeDefs defined above. Then below is the code to run the query:
const client = createClient();
const data = client.readQuery({query: gql`
{
alert #client
}
`});
console.log('data:', data);
But I got this error Missing selection set for object of type Alert returned for query field alert when run readQuery on the client instance. It seems that the Alert is not defined. But I already defined the Alert query in the typeDefs. It works fine if I change the query code to below which I have to specify what to be returned inside { message }. But it doesn't seem to use the schema. What I expect is that I don't need to specify the return fields if it returns all fields in the schema object. Do I mis-understand the schema?
const data = client.readQuery({query: gql`
{
alert #client {
message
}
}
`});
console.log('data:', data);
If I have to specify the return fields one by one, what the point to define the schema?
This is expected behavior with GraphQL. You always need to specify inside the query which fields you're expecting. So in order to receive all the data you add the fields to the query:
const data = client.readQuery({query: gql`
{
alert #client {
message
type
duration
}
}
`});
console.log('data:', data);
There is an open issue inside the GraphQL specs.
You can define a fragment with all the fields of the entity and then reuse it.
Like this
fragment AllAlertFields on Alert {
message
type
duration
}
And then in a query
query {
allAlerts {
...AllAlertFields
}
}
More details: https://www.apollographql.com/docs/react/data/fragments/

Apollo and AwsAppsync repeating mutation in callback

I have an awsAppSync client that is set up as follows:
that._getClient = function() {
return client = new AWSAppSyncClient({
url: appSyncUrl,
region: AWS.config.region,
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: AWS.config.credentials
}
});
}
And a mutate function that is called like this:
that.mutate = function(mutation, variables) {
let client = that._getClient();
return client.mutate({ mutation: mutation, fetchPolicy: 'no-cache', variables: variables })
.then(function (result){
return result;
});
}
I need to make subsequent queries to create different records that depend on one another, so I'm returning the Id of the newly created record to use in the callback of the previous query.
The problem is, that in every callback where the mutate function is called, the mutation that caused this callback gets executed again. For example, I do:
appSync.mutate(mutation, requestParams)
.then(function (response) {
let id = response.id
requestParams = {//new stuff}
return appSync.mutate(mutation, requestParams)
})
.then(//and so forth)
Now, I've seen some posts on here that say that it might be something to do with the optimistic response, and so on, but I actually get two new records in my database. I also considered the cache doing something trippy, but As you can see from the code, I (think) disabled it for the mutation.
Please help.

With apollo client how do you set loading status on mutation refetchQueries?

So I'm adding to an object's list with a mutation using the apollo client. Say I have an event and I'm adding participants and i'm using refetchQueries to get the refreshed event with participants on the details screen. Unfortunately I'm not getting a data.loading == true status during this refetch, making it likely that the user will keep hitting that join participant button repeatedly.
<Button styleName="dark full-width" onPress={()=> {
this.props.joinEvent({
variables: { eventId: Event.id, userId: user.id },
refetchQueries: ['getEvent'],
});
// how do I trigger the data.loading = true like it does during the initial fetch?
}
}>
use awaitRefetchQueries:true, it will wait until refetch query resolves
awaitRefetchQuery
The Apollo React documentation isn't great on this, but there is an open issue to improve it.
Instead of looking at the data.loading property, you'll want to use data.networkStatus. It will change to 4 during a refetch (networkStatus values).
However, in order to get this value to update, you'll also need to set the notifyOnNetworkStatusChange option to true in your query options.
Using the React graphql higher-order component, this looks like:
var myQuery = gql`
query MyQuery {
...
}
`;
var myComponentWithData = graphql(myQuery, {
options: {
notifyOnNetworkStatusChange: true
}
}
)(MyComponent);

Resources