Skip to content

Suspense and conditional fetching causing infinite rerenders #1660

@shuding

Description

@shuding

Discussed in #1651

Originally posted by rikutiira November 22, 2021
Hey, and first of all thanks for the great work on the library!

I'm new to SWR and I have been reading discussion & GH issues around this, and I'm still a bit unsure about how suspense and conditional fetching should work with the latest version (1.1.0-beta.9 at the time of writing this) so I was hoping to get some clarity around the issue 😄.

I'm having an infinite rerender issue when using suspense with conditional fetching from version 1.0.0 onwards (including current beta).

The SWR documentation on Suspense says that with conditional fetching, data should be undefined but with version 1.0.0+, it seems to fallback to the Suspense component instead and causes an infinite render loop where the useSWR hook is called. I'm new to suspense, but I suppose this is not expected behaviour?

  1. Am I doing something wrong in the code?
  2. Is the behaviour expected? If it is, how are you supposed to deal with conditional data fetching? Is there any additional documentation on the subject somewhere?

Here is a Codesandbox where you can test the issue: https://codesandbox.io/s/cold-dust-4dvzl?file=/src/App.js (uncomment response to run it). Here's the code as well:

import React, { useState, Suspense } from "react";
import useSWR from "swr";
import "./styles.css";

const fetcher = (str) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(str);
    }, 1000);
  });
};

const Test = (props) => {
  console.log("renders");

  const response = useSWR(props.str ?? null, fetcher, { suspense: true });

  return (
    <>
      <div>Data:</div>
      <pre>{JSON.stringify(response, null, 2)}</pre>
    </>
  );
};

export default function App() {
  const [str, setStr] = useState();
  return (
    <div className="App">
      <h1>SWR test</h1>
      <Suspense fallback={<div>loading...</div>}>
        <Test str={str} />
      </Suspense>
      <button onClick={() => setStr("hello world")}>Clicky</button>
    </div>
  );
}

Thanks! 🙇

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions