TanStack / query

🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.
https://tanstack.com/query
MIT License
42.87k stars 2.94k forks source link

Upgrading 5.15.0 -> 5.17.0 causes severe lag when switching from specific route to another #6631

Closed fl-y closed 11 months ago

fl-y commented 11 months ago

Describe the bug

Took half a work day to figure out it was due to a minor upgrade issue but you can see this happening when switching routes from the /withdraw page and then clicking on the stake menu on this commit which takes much longer than this commit

Took a while but I've pinned it down to this only occurring when upgrading @tanstack/react-query, @tanstack/react-query-devtools, @tanstack/react-query-persist-client version from 5.15.0 to 5.17.0

I haven't figured out exactly what the cause is but only know for certain it's from tanstack.

One symptom I've noticed is that on redux devtools extension it seems to spam navigate as can be seen in this loom recording https://www.loom.com/share/9afe86017be8422eb36cd5fc61c0d677

Here are the list of dependencies I'm using on the project.

"dependencies": {
        "@formkit/auto-animate": "^0.8.0",
        "@rollbar/react": "^0.11.2",
        "@tailwindcss/typography": "^0.5.10",
        "@tanstack/react-query": "5.17.0",
        "@tanstack/react-query-devtools": "5.17.0",
        "@tanstack/react-query-persist-client": "5.17.0",
        "@upstash/redis": "^1.25.1",
        "@vercel/analytics": "^1.1.1",
        "camelcase-keys": "^9.1.2",
        "chain-config": "workspace:*",
        "class-variance-authority": "^0.7.0",
        "clsx": "2.0.0",
        "common": "workspace:*",
        "copy-to-clipboard": "^3.3.3",
        "cosmos-client": "workspace:*",
        "dayjs": "^1.11.10",
        "eventemitter3": "^5.0.1",
        "framer-motion": "10.16.16",
        "geist": "^1.0.0",
        "idb-keyval": "^6.2.1",
        "is-mobile": "^4.0.0",
        "jotai": "^2.6.0",
        "lodash-es": "^4.17.21",
        "million": "^2.6.4",
        "next": "^14.0.4",
        "next-usequerystate": "1.13.2",
        "pusher-js": "8.4.0-rc2",
        "react": "^18.2.0",
        "react-aria": "^3.29.1",
        "react-aria-components": "1.0.0",
        "react-dom": "^18.2.0",
        "react-draggable": "^4.4.6",
        "react-singleton-hook": "^4.0.1",
        "react-toastify": "^9.1.3",
        "react-wrap-balancer": "^1.1.0",
        "rollbar": "^2.26.2",
        "sharp": "^0.33.0",
        "tailwind-merge": "^2.0.0",
        "tailwind-scrollbar-hide": "^1.1.7",
        "tailwindcss-animate": "^1.0.7",
        "type-fest": "^4.9.0",
        "ui": "workspace:*",
        "wallets": "workspace:*",
        "zod": "^3.22.4"
    },
    "devDependencies": {
        "@keplr-wallet/types": "^0.12.38",
        "@next/bundle-analyzer": "^14.0.3",
        "@trivago/prettier-plugin-sort-imports": "^4.2.1",
        "@types/lodash-es": "^4.17.10",
        "@types/node": "^20.10.5",
        "@types/react": "^18.0.22",
        "@types/react-dom": "^18.0.7",
        "autoprefixer": "^10.4.16",
        "cross-env": "^7.0.3",
        "javascript-obfuscator": "^4.1.0",
        "next-sitemap": "^4.2.3",
        "nextjs-obfuscator": "^3.0.0",
        "postcss": "^8.4.31",
        "prettier": "^3.0.3",
        "prettier-plugin-tailwindcss": "^0.5.6",
        "sass": "^1.69.5",
        "tailwindcss": "^3.3.5",
        "tailwindcss-react-aria-components": "1.0.0",
        "tsconfig": "workspace:*",
        "typescript": "^5.2.2"
    },

node: 18.18.2 pnpm: 8.13.1 happens everywhere, dev, local builds, deployed on Vercel. I use the app directory on Nextjs and turborepo.

This is my nextjs config

const nextConfig = {
    poweredByHeader: false,

    output: 'standalone',
    experimental: {
        outputFileTracingRoot: path.join(__dirname, '../../'),
        // turbotrace: {
        //  // control the log level of the turbotrace, default is `error`
        //  logLevel: 'error',
        //  // control if the log of turbotrace should contain the details of the analysis, default is `false`
        //  logDetail: true,
        //  // show all log messages without limit
        //  // turbotrace only show 1 log message for each categories by default
        //  logAll: false,
        //  // control the context directory of the turbotrace
        //  // files outside of the context directory will not be traced
        //  // set the `experimental.outputFileTracingRoot` has the same effect
        //  // if the `experimental.outputFileTracingRoot` and this option are both set, the `experimental.turbotrace.contextDirectory` will be used
        //  // control the maximum memory usage of the `turbotrace`, in `MB`, default is `6000`.
        //  memoryLimit: 6000
        // },
    },

    reactStrictMode: true,
    compiler: {
        removeConsole: {
            //  do display errors in production
            exclude: process.env.NODE_ENV === 'production' ? ['error'] : ['error', 'warn', 'log', 'info', 'debug'],
        },
    },
    swcMinify: true,
    transpilePackages: ['ui'],
    async redirects() {
        if (process.env.NODE_ENV === 'production')
            return playgroundRoutes.map(route => ({
                source: '/playground' + route,
                destination: '/',
                permanent: false,
            }))
        return []
    },
}

const playgroundRoutes = ['/ibc-hooks', '/ibc-query', '/liquid-staking', '/test', '/playground/wallet-connect']

const plugins = [withBundleAnalyzer({ enabled: process.env.ANALYZE === 'true' })]
// if (process.env.NODE_ENV !== 'production') plugins.push(withObfuscator)

const millionConfig = {
    auto: { rsc: true },
}

export default () => {
    if (process.env.NODE_ENV === 'production')
        return million.next(
            plugins.reduce((acc, plugin) => plugin(acc), { ...nextConfig }),
            millionConfig,
        )

    return plugins.reduce((acc, plugin) => plugin(acc), { ...nextConfig })
}

Your minimal, reproducible example

Explained above

Steps to reproduce

Explained above

Expected behavior

The route to load without 'navigate' spamming

How often does this bug happen?

Every time

Screenshots or Videos

Posted above

Platform

platform agnostic

Tanstack Query adapter

react-query

TanStack Query version

5.17.0

TypeScript version

^5.2.2

Additional context

Appreciate all things tanstack so much sir - the one package I cannot live without 🫡

fl-y commented 11 months ago

Please lmk if this info is not enough to figure this out - I'm much more available on twitter, feel free to reach out on https://twitter.com/cosmonaut_joon

TkDodo commented 11 months ago

Please create a small codesandbox reproduction that shows the issue.

KurtGokhan commented 11 months ago

I am having an issue with useQueries after version 5.15.5. It is causing 1000s of rerenders in a second, quickly bringing the browser to a freeze. I suspect this commit is the culprit.

I could not reproduce this in code sandbox yet. I will open an issue when I can. But I would appreciate if you could fix this if you have an idea what might be causing this.

TkDodo commented 11 months ago

@KurtGokhan yes please create a separate issue, I wouldn't want to mix issues around useQuery with ones about useQueries.

The commit you showed revert a change and added another condition to the early bailout from setData (&& newObservers.length > 0) which should only have an effect if you call useQueries with an empty array. So I don't immediately see how this could lead to infinite re-renders (we also have tests to guard against this I think)

fl-y commented 11 months ago

Noticed the issue was fixed on the latest version, I think the referenced merge PR fixed it - closing. Sorry for not supplying extra info, forgot to keep tabs on the issue 🙈

Appreciate it sir 🫡