1
votes

currently trying out react hooks & react suspense. I'm trying to make a hook useApolloQuery which would fetch some data and throw a promise to wait till the data loads.

I'm putting the logic to fetch the data in a useEffect, but it seems like the effect never gets run if you instantly throw a promise in the component (and thus suspend it).

Here's my code: (Or codesandbox link: https://codesandbox.io/s/x73pwj164q )

function createPromiseResolver() {
  let resolve;
  const promise = new Promise(newResolver => {
    resolve = newResolver;
  });

  return { resolve, promise };
}

function useApolloQuery() {
  const [data, setData] = useState();
  const promsieResolver = createPromiseResolver();

  console.log("this runs");
  useEffect(() => {
    console.log("this doesn't run");

    const timeoutId = setTimeout(() => {
      setData("Some fake data");
      promsieResolver.resolve();
    }, 500);

    return () => clearTimeout(timeoutId);
  });

  if (!data) throw promsieResolver.promise;

  return data;
}

function App() {
  const data = useApolloQuery();

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>{data}</h2>
    </div>
  );
}

So in that code only the first console.log runs, since the useEffect hook never runs

Is suspense supposed to work like this? Any way to make it work?

2

2 Answers

2
votes

The useEffect doesn't run because you are throwing a promise before the actual function returns, so the promise is never resolved.

The problem is in the line

if (!data) throw promsieResolver.promise;

Initial data is undefined and thus !data = true. It throws a promise and thus the function is never returned but short-circuited. Removing this line actually runs the useEffect hook

Solution 2: Or you could set an initial state for data other than undefined as below const [data, setData] = useState('initial data');

0
votes

Just found this: https://github.com/facebook/react/issues/14563#issuecomment-453184356 So looks like there's no way around this except for keeping all the state in an external store