ecyrbe / zodios-react

React hooks for zodios
MIT License
64 stars 12 forks source link

Help : infinite loop when consuming hook #468

Closed cyrilchapon closed 10 months ago

cyrilchapon commented 10 months ago

Hi,

First of all, thanks for this library. It's very promising, I already love it.

I'm getting a render infinite loop; but I suspect this is because I'm doing something wrong that I cannot nail down. Here's the setup :

package.json

    "@tanstack/react-query": "^4.36.1",
    "@zodios/core": "^10.9.6",
    "@zodios/react": "^10.4.5",
    "axios": "^1.6.2",

api-def.ts

import { makeApi } from '@zodios/core'

export const getWord = makeEndpoint({
  method: 'get',
  path: '/word',
  response: daywordDTO.nullable(), // Some DTO zod schema, skipped for clarity
  alias: 'getWord',
  description: 'Get a word',
})

export const apiDefinition = makeApi([getWord])

export type ApiDefinition = typeof apiDefinition

api.ts

import { QueryClient } from '@tanstack/react-query'
import { Zodios } from '@zodios/core'
import { ZodiosHooks } from '@zodios/react'

import { apiDefinition } from './api-def'

export const apiClient = new Zodios(process.env.EXPO_PUBLIC_API_URL, apiDefinition, {
  validate: true,
  transform: 'response',
})

export const apiHooks = new ZodiosHooks('word-api', apiClient)
export const queryClient = new QueryClient()

app.tsx

import { QueryClientProvider } from '@tanstack/react-query'

import { Component } from './component'
import { queryClient } from '../api'

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Component />
    </QueryClientProvider>
  )
}

component.tsx

import { FunctionComponent } from 'react'
import { View } from 'react-native'
import { Text } from 'react-native-paper'

import { apiHooks } from '../api'

export const Component: FunctionComponent = (props) => {
  const {
    data: wordData,
    isSuccess,
    isLoading,
  } = apiHooks.getWord(
    {},
    {
      // TODO: debug infinite loop
     enabled: false
    },
  )

  console.log('render')

  return (
    <View>
      <Text>
        {!isLoading
          ? isSuccess ? wordData?.word ?? 'none' : 'erreur'
          : 'loading'
        }
      </Text>
    </View>
  )
}

Once I remove enabled: true (or even call refetch()); I get an infinite loop

render render render render ...

(I confirm the HTTP request resolves correctly to 200. In fact the infinite loop ONLY happens if it's 200. Otherwise, it just retries correctly occasionally)


I tried

    {
      // TODO: debug infinite loop
      refetchOnWindowFocus: false,
      refetchOnReconnect: false,
      refetchInterval: false,
      refetchIntervalInBackground: false,
      refetchOnMount: false,
      retry: false,
      staleTime: 1000 * 60,
    },

Without any difference


Any idea of what I might be doing wrong ? Thanks ! NB: as you noticed, I'm on react-native

cyrilchapon commented 10 months ago

My bad, stupid new Date(Date.now()) in my render function passed to params in my actual world use-case.

Closing