Skip to content

Commit

Permalink
docs(react): update the react-native.md section (#8506)
Browse files Browse the repository at this point in the history
* update the doc

* update the doc

---------

Co-authored-by: Dominik Dorfmeister <[email protected]>
  • Loading branch information
flodlc and TkDodo authored Jan 8, 2025
1 parent 80490f1 commit 67ac48a
Showing 1 changed file with 9 additions and 88 deletions.
97 changes: 9 additions & 88 deletions docs/framework/react/react-native.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,108 +92,29 @@ export function useRefreshOnFocus<T>(refetch: () => Promise<T>) {

In the above code, `refetch` is skipped the first time because `useFocusEffect` calls our callback on mount in addition to screen focus.

## Disable re-renders on out of focus Screens

In some situations, including performance concerns, you may want to stop re-renders when a React Native screen gets out of focus. To achieve this we can use `useFocusEffect` from `@react-navigation/native` together with the `notifyOnChangeProps` query option.

This custom hook provides a `notifyOnChangeProps` option that will return an empty array whenever a screen goes out of focus - effectively stopping any re-renders on that scenario. Whenever the screens gets in focus again, the behavior goes back to normal.

```tsx
import React from 'react'
import { NotifyOnChangeProps } from '@tanstack/query-core'
import { useFocusEffect } from '@react-navigation/native'

export function useFocusNotifyOnChangeProps(
notifyOnChangeProps?: NotifyOnChangeProps,
) {
const focusedRef = React.useRef(true)

useFocusEffect(
React.useCallback(() => {
focusedRef.current = true

return () => {
focusedRef.current = false
}
}, []),
)

return () => {
if (!focusedRef.current) {
return []
}

if (typeof notifyOnChangeProps === 'function') {
return notifyOnChangeProps()
}

return notifyOnChangeProps
}
}
```

In the above code, `useFocusEffect` is used to change the value of a reference that the callback will use as a condition.
## Disable queries on out of focus screens

The argument is wrapped in a reference to also guarantee that the returned callback always keeps the same reference.
If you don’t want certain queries to remain “live” while a screen is out of focus, you can use the subscribed prop on useQuery. This prop lets you control whether a query stays subscribed to updates. Combined with React Navigation’s useIsFocused, it allows you to seamlessly unsubscribe from queries when a screen isn’t in focus:

Example usage:

```tsx
function MyComponent() {
const notifyOnChangeProps = useFocusNotifyOnChangeProps()

const { dataUpdatedAt } = useQuery({
queryKey: ['myKey'],
queryFn: async () => {
const response = await fetch(
'https://api.github.com/repos/tannerlinsley/react-query',
)
return response.json()
},
notifyOnChangeProps,
})

return <Text>DataUpdatedAt: {dataUpdatedAt}</Text>
}
```

## Disable queries on out of focus screens

Enabled can also be set to a callback to support disabling queries on out of focus screens without state and re-rendering on navigation, similar to how notifyOnChangeProps works but in addition it wont trigger refetching when invalidating queries with refetchType active.

```tsx
import React from 'react'
import { useFocusEffect } from '@react-navigation/native'

export function useQueryFocusAware() {
const focusedRef = React.useRef(true)

useFocusEffect(
React.useCallback(() => {
focusedRef.current = true

return () => {
focusedRef.current = false
}
}, []),
)

return () => focusedRef.current
}
```

Example usage:
import { useIsFocused } from '@react-navigation/native'
import { useQuery } from '@tanstack/react-query'
import { Text } from 'react-native'

```tsx
function MyComponent() {
const isFocused = useQueryFocusAware()
const isFocused = useIsFocused()

const { dataUpdatedAt } = useQuery({
queryKey: ['key'],
queryFn: () => fetch(...),
enabled: isFocused,
subscribed: isFocused,
})

return <Text>DataUpdatedAt: {dataUpdatedAt}</Text>
}
```

When subscribed is false, the query unsubscribes from updates and won’t trigger re-renders or fetch new data for that screen. Once it becomes true again (e.g., when the screen regains focus), the query re-subscribes and stays up to date.

0 comments on commit 67ac48a

Please sign in to comment.