swr icon indicating copy to clipboard operation
swr copied to clipboard

UseSwr being called twice, i have done everything but fetched is called twice

Open Jazzykhan opened this issue 2 years ago • 4 comments

Bug report

Description / Observed Behavior

with simple next.js project i am suing useSwr in index.js and i saw that console.log(data); just after useSwr is called twice no matter what.

What kind of issues did you encounter with SWR? data is being fetched twice.

Expected Behavior

It should be fetched once only.

How did you expect SWR to behave here? twice calling?

Repro Steps / Code Example

_app.js ` import "../styles/globals.css"; import "antd/dist/antd.css"; import { Layout, Menu, Breadcrumb } from "antd"; import Home from "."; import MainMenu from "./navbars/main-menu"; const { Header, Content, Footer } = Layout; import { QueryClient, QueryClientProvider } from "react-query"; import { ReactQueryDevtools } from "react-query/devtools"; const queryClient = new QueryClient();

function MyApp({ Component, pageProps }) { // return <Component {...pageProps} /> return ( Layout Home Layout ); }

export default MyApp;

index.js import Head from "next/head"; import Image from "next/image"; import styles from "../styles/Home.module.css";

import useSWR from "swr"; const fetcher = (url) => fetch(url).then((res) => res.json()); export default function Home() { const { data, error } = useSWR("https://reqbin.com/echo/get/json", fetcher);

console.log(data);

return (

Done

); }

` Screenshot of issue: image

Or share your code snippet or a CodeSandbox link is also appreciated!

Additional Context

SWR version. Add any other context about the problem here.

"swr": "^1.3.0"

Jazzykhan avatar May 05 '22 19:05 Jazzykhan

If you're using React 18 and StrictMode, it's likely this is the result of intentional React behaviour:

https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state

With Strict Mode starting in React 18, whenever a component mounts in development, React will simulate immediately unmounting and remounting the component

basically useEffect and friends will run twice, in development mode only.

beforan avatar Jun 16 '22 09:06 beforan

Hi @Jazzykhan ,

I was able to avoid multiple fetching of the same data with useSWRImmutable: https://swr.vercel.app/docs/revalidation#disable-automatic-revalidations

Best regards Davide

davidecrs avatar Jun 16 '22 09:06 davidecrs

I meet the same problem and I try this approach as above. I revise the fetch function like useSWRImmutable but it doesn't work.

qqc0821 avatar Jun 21 '22 13:06 qqc0821

Yeah same issue as of now, I noticed that my code is being logged twice thus as soon as I use useSWR. Here is my code example.

import useSWR from "swr";

const fetcher = url => fetch(url).then(r => r.json());

export default function Home() {
  const { data } = useSWR("https://dog.ceo/api/breeds/image/random", fetcher, {
    revalidateIfStale: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false
  });

  console.log("it is being called twice");

  return (
    <div></div>
  );
}

The console log below: image

I already removed react strict mode but swr is definitely the issue. Hope we got solution to this problem soon.

ZhenFTW avatar Aug 05 '22 07:08 ZhenFTW

I'm having the same issue

maurice-ellis avatar Nov 05 '22 03:11 maurice-ellis

I am also facing the same issue , but in options if you give suspense as true it is rendering only once

GouthamJM avatar Nov 10 '22 07:11 GouthamJM

Example: https://codesandbox.io/s/swr-1952-forked-zqncu5?file=/src/App.js

When using SWR

  • Fetcher will only be called once
  • Component will render twice (four times in strict mode) first data -> undefined second data -> somthing
  • see more details in https://swr.vercel.app/docs/advanced/performance

promer94 avatar Jan 30 '23 08:01 promer94

Well guys I solved this problem by doing like this:

// in service
const { data, error, isLoading } = useSWRImmutable(URL, getLocations);

return {
    ranking: data,
    isLoading,
    error
}


// in component
if (!isLoading)
    rankingNames = getRankingNames[0].res

leandroslopes avatar Aug 09 '23 17:08 leandroslopes

I use Vite, and this is my stupid way

import { AxiosRequestConfig } from 'axios';
import { useEffect, useMemo, useRef } from 'react';

// ref: https://vitejs.dev/guide/env-and-mode#node-env-and-modes
const isStrictMode = import.meta.env.MODE !== 'production';

export function useReqCancel(reqConfig: AxiosRequestConfig, cancelableReq: boolean) {
  const firstCancel = useRef(true);
  const abortController = useMemo(
    () => (cancelableReq ? new AbortController() : null),
    [cancelableReq]
  );
  if (abortController) {
    reqConfig.signal = abortController.signal;
  }

  useEffect(() => {
    return () => {
      if (firstCancel.current && isStrictMode) {
        firstCancel.current = false;
        return;
      }
      firstCancel.current = false;

      if (cancelableReq) {
        abortController?.abort();
      }
    };
  }, [cancelableReq, firstCancel, abortController]);
}

markhuang19994 avatar Feb 19 '24 15:02 markhuang19994

An easier route is to add dedupingInterval: Infinity to the useSWR options.

carlos-menezes avatar Feb 24 '24 23:02 carlos-menezes