2

Using useSWR to retrieve data from an endpoint, but I am getting this error (I want to only retrieve the data onclick)

"useSWR is called in function `fetchUsers` that is niether a React function component nor a custom React Hook function" Error 
const [shouldFetch,setShouldFetch] = useState(false)
const fetcher = (url) => axios.get(url).then((res) => res.data);
    const { data, error } = useSWR(shouldFetch ? "http://localhost:5000/users": null, fetcher);
    )

The fetchUsers function is being called here onclick:

        <Box>
        <Button
          onClick= setShouldFetch(true)
        >
          View User
        </Button>
      </Box>

the block of code below should render the retrieved API response. If setShouldFetch is true, then the API response is rendered, if not, something else is rendered. Here's my current implementation, but it's returning an error cannot read properties of undefined (reading 'name)

             <Typography
              >
                shouldFetch? data.name : Students Portal
              </Typography>

This is what the expected response looks like:

   {
        "name": [
            {
                "id": "8",
                "age": "10"
            },
            {
                "id": "4",
                "age": "11",
            }
        ],
        "id": "71"
    }
Tini
  • 169
  • 8
  • 1
    Commented down below, don't use `shouldFetch ? ....` use `data ? ...` – Adam Jenkins Dec 07 '22 at 02:02
  • I tried ```data? data.name: Students Portal ``` but I got nothing rendered on the page Checking the Browser Network tab, the request was successful. – Tini Dec 07 '22 at 11:48
  • Then something else is wrong, you'll have to show more of your component code. – Adam Jenkins Dec 07 '22 at 11:55
  • This is basically everything. The console shows the error: ```Uncaught Error: Objects are not valid as a React Child. If you meant to render a collection of children, use an array instead``` – Tini Dec 07 '22 at 15:28
  • 1
    Tini - that's a different problem. That's no longer related to this question, this question has been answered in a way that works for you. What you're doing to get that error is you're trying to render an object instead of a string or a number. You'd get that error if you tried to do something like this: `<>{data}>`, but please open a different question (or google for the answer). This will help: https://stackoverflow.com/questions/52428879/objects-are-not-valid-as-a-react-child-if-you-meant-to-render-a-collection-of-c – Adam Jenkins Dec 07 '22 at 15:41

1 Answers1

2

You want conditional data fetching

In your example I think it could be something like this:

const [shouldFetch,setShouldFetch] = useState(false)
const fetcher = (url) => axios.get(url).then((res) => res.data);
const { data, error } = useSWR(shouldFetch ? 'http://...' : null,fetcher)

return (
       <Box>
        <Button
          onClick={() => setShouldFetch(true)}
        >
          View User
        </Button>
      </Box>
)

To discuss this a little bit, with declarative data fetching the fetch is called immediately and automatically when the component is rendered unless you make it conditional. In the case of useSWR it won't fetch automatically if your key (first parameter to useSWR) is null or is a function that returns null or is a function that throws an error.

Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100
  • In this case, how can I implement conditional rendering? For instance, I want to render the API response when `setShouldFetch` is true, which is onClick. I'm currently getting `cannot read properties of undefined (reading `name`).` I have updated my question to show what I have tried. – Tini Dec 07 '22 at 01:48
  • @Tini - No, you don't want to render the API response when `shouldFetch` is `true` because there's no guarantee that you'll have an API response, just that useSWR will be attempting to make one. What you want is to render the response when `data` from `useSWR` is not `undefined` – Adam Jenkins Dec 07 '22 at 02:01