menu

Apollo

A community of developers, designers and others who love Apollo and GraphQL. 🚀

Channels
# All channels
view-forward
# General
view-forward
# Apollo Angular
view-forward
# Announcements
view-forward
# Apollo Android
view-forward
# Apollo Client
view-forward
# Apollo iOS
view-forward
# Apollo Link
view-forward
# Apollo Link Rest
view-forward
# Local State
view-forward
# Apollo Studio
view-forward
# Apollo Server
view-forward
# Apollo Tooling
view-forward
# Contributing
view-forward
# Docs
view-forward
# Events
view-forward
# GraphQL Tools
view-forward
# Jobs
view-forward
# Random
view-forward
# React Apollo
view-forward
# Showcase
view-forward
# Subscriptions
view-forward
# Testing
view-forward
# Vue Apollo
view-forward
Team

React re-render causing Apollo useQuery to be called twice

April 12, 2021 at 5:26pm
The Apollo community has a new home. This thread is preserved for historical purposes. The content of this conversation may be innaccurrate or out of date. Go to new community home →

React re-render causing Apollo useQuery to be called twice

April 12, 2021 at 5:26pm (Edited 1 month ago)
I have a simple React component that uses Apollo's useQuery to fetch data. The problem is, because the component is being re-rendered by Apollo, it is calling useQuery twice, which is then calling the Apollo resolver twice, which is then calling the associated function that fetches and returns the data twice, which we can all agree is not great.
Is there something I'm doing wrong? How do I stop the data fetching function from being called multiple times?
Project Details:
A simple console.log statement in the data fetching function is showing that it is getting called twice.
import { useEffect } from "react";
import { useQuery, useMutation, gql } from "@apollo/client";
import { Wrapper, Title } from "./App.styles";
const GET_SIGNALS = gql`query { charts { symbol price } }`;
const App = () => {
const { loading, error, data } = useQuery(GET_SIGNALS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error...</p>;
console.log(data);
return (
<Wrapper>
<Title>Trend List</Title>
</Wrapper>
);
};
export default App;
Here's the Apollo server:
import { ApolloServer, gql } from "apollo-server-micro";
import { getCharts } from "../../src/getCharts";
const typeDefs = gql`
type Chart {
symbol: String
price: [String]
}
type Query {
charts: [Chart]
}
`;
const resolvers = {
Query: {
charts: () => getCharts(),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const handler = server.createHandler({ path: "/api/graphql-api" });
export const config = {
api: {
bodyParser: false,
},
};
export default handler;
The getCharts() functions just returns an object that fits the type definitions.
export const getCharts = async () => {
console.log("1. Starting getCharts");
return [{ symbol: "BTCUSDT", price: ["1", "2", "3"] }];
};
So the output is:
1. Starting getCharts
2. Starting getCharts

April 12, 2021 at 5:30pm
consider using useLazyQuery instead of useQuery which will let you have finer grained control as to when your query is fired, the syntax will look like something like: const [fireGetSignals, { loading, error, data }] = useLazyQuery(GET_SIGNALS); fireGetSignal being a function you can call whenever you'd like.
Edited
like-fill
1
  • reply
  • like
(erik-rahm) Thank you!!!! Your solution worked. I put it in a useEffect hook. Weird that the default behaviour of Apollo is to allow two calls, no?
  • reply
  • like

April 14, 2021 at 8:28pm
(bengrunfeld) It's not that it allows for two calls persay, it's that the component you had useQuery in is updating without remote data in mind, so you are causing rerenders through things like setting state or some other operation that has a lifecycle updating side effect like the component receiving new props which is then causing the entire component to rerender including the useQuery hook. This can be really useful in a lot of situations but can be less than desirable in others!
  • reply
  • like