Search code examples
reactjsnext.jsswr

SWR hook error: "An argument for 'Fetcher' was not provided"


It's my first time using SWR hook, and everything is working great actually. But I have an error and I really don't know what is going there, so let me show you my code first.

This is global configuration

<AuthContext>
    {isValidRoute && <Navbar />}
    <SWRConfig
        value={{
          fetcher: (url: string) => axios.get(url).then(res => res.data)
        }}
    >
        <Component {...pageProps} />
    </SWRConfig>
</AuthContext>

And this is where I'm using it

import useSWR from "swr";

import { NavbarPart3 } from "../NavbarStyled";
import { dataObject } from "../../../GlobalInterfaces/AuthContextInterfaces";

const Part3 = () => {
  if (typeof window !== "undefined") {
    const userId: dataObject = JSON.parse(localStorage.getItem("Auth"));
    const { data } = useSWR(
      "http://localhost:5000/api/user/singleU/" + userId.user.id
    );
    console.log(data);
  }

  return <NavbarPart3></NavbarPart3>;
};

export default Part3;

Now, this is the ERROR

Expected 4 arguments, but got 1.ts(2554)
use-swr.d.ts(4, 91): An argument for 'Fetcher' was not provided

The Goal: I just want to get rid of that problem. Do you know what might be causing this problem?


Solution

  • TL;DR: The SWRConfig provider where you define the global fetcher needs to wrap the component where useSWR is called.


    I'm assuming you're calling the Part3 component somewhere within your NavBar component, which would explain the error you're seeing.

    You have to move {isValidRoute && <Navbar />} inside the SWRConfig provider.

    <AuthContext>
        <SWRConfig
            value={{
                fetcher: (url: string) => axios.get(url).then(res => res.data)
            }}
        >
            {isValidRoute && <Navbar />}
            <Component {...pageProps} />
        </SWRConfig>
    </AuthContext>
    

    As a side note, do not conditionally call useSWR (which is a custom React hook) as that will break the Rules of Hooks.

    In your Part3 component, move the useSWR call to the top-level of your component and the localStorage call inside a useEffect.

    const Part3 = () => {
        const [userId, setUserId] = useState()
        const { data } = useSWR(
            // Using the arrow function syntax so that the request is only made when `userId.user.id` is valid
            () => "http://localhost:5000/api/user/singleU/" + userId.user.id
        );
    
        useEffect(() => {
            const auth = JSON.parse(localStorage.getItem("Auth"));
            setUserId(auth);
        }, []);
    
        console.log(data);
    
        return <NavbarPart3></NavbarPart3>;
    };