Search code examples
reactjsreact-hooksapolloreact-apolloreact-apollo-hooks

Using hooks with Apollo Provider


Here is a Codesandbox link recreating the issue: https://codesandbox.io/s/boring-nash-svcj7?file=/src/index.js

I'm having a weird issue. I have a very simple setup Apollo setup just for testing purposes. It goes like this:

function App() {
  return (
    <ApolloProvider client={client}>
      <Main />
    </ApolloProvider>
  );
}

It's just a simple ApolloProvider that provides the client to the App component. The App component just has one line.

const Main = () => {
  const [data, setData] = useState();
  setData(1);
  return <div>Test</div>;
};

Now, when I refresh my page, I get this error:

Too many re-renders. React limits the number of renders to prevent an infinite loop.

Does anyone know what's going on here?

Why can't I use a simple hook inside of my component?

Here is the full code:

import React, { useState } from "react";
import ReactDOM from "react-dom";

import ApolloClient from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";
import { ApolloProvider } from "@apollo/react-hooks";

const client = new ApolloClient({
  link: new HttpLink({
    uri: "https://api.graph.cool/simple/v1/swapi"
  }),
  cache: new InMemoryCache()
});

const Main = () => {
  const [data, setData] = useState();
  setData(1);
  return <div>Test</div>;
};

function App() {
  return (
    <ApolloProvider client={client}>
      <Main />
    </ApolloProvider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

There is an example I was following where it does work, so I'm not sure why my example isn't.

https://codesandbox.io/s/replace-previous-results-with-next-results-nuu6x?file=/src/FilmTitles.jsx:16-24


Solution

  • Well you cannot setState in render function of the component. And for functional components their body is the render function. In this case setData updates the state which triggers re-rendering and on each render it calls setData again in the infinite loop:

    function App() {
        const [data, setData] = useState(0);
        setData(1); // this triggers re-render which is execution of App() which again calls setData(1)
    }