GeekyAnts / GeekyAnts/NativeBase
Components re-render when device rotates even if breakpoint does not change
- Dominant language
- TypeScript
- Stars
- 20.4k
- Forks
- 2.4k
- PR merge metrics
- No merged PRs in 30d
Description
### Description
NativeBase components rerender unnecessarily
### CodeSandbox/Snack link
https://snack.expo.dev/@n_harada/nativebasebreakpointsexample
### Steps to reproduce
Open the snack on a device.
1. See a number having been incremented at regular intervals at the center of screen.
2. Rotate device.
3. You can see the count incrementation stops for several seconds.
(4. If you can put logger into your NativeBase code, you can see this occurs due to unnecessary re-rendering)
### NativeBase Version
3.2.1
### Platform
- [ ] Android
- [ ] CRA
- [X] Expo
- [ ] iOS
- [ ] Next
### Other Platform
_No response_
### Additional Information
NativeBase components re-render when screen size changes and break points value does not matter with this re-rendering.
Even if breakpoint does not change, re-rendering occurs.
It is because usePropsResolutionWithComponentTheme fires when useWindowDimensions's state changes and return value of usePropsResolutionWithComponentTheme is different object every time.
Also, ReactNative's useWindowDimensions has a bug(([https://github.com/facebook/react-native/issues/29290](https://github.com/facebook/react-native/issues/29290)) of which useWindowDimensions returns wrong value and the value are swapped for a very short amount of time([https://github.com/facebook/react-native/issues/29290#issuecomment-696537458](https://github.com/facebook/react-native/issues/29290#issuecomment-696537458)).
I faced that swapping when iPad app comes to foreground.
This useWindowDimensions'bug combined with NativeBase re-rendering, my app on iPad freezes several seconds every time when it comes to foreground.
I came up with two solutions about this problem with useWindowDimensions'bug.The first one is making NB components render only when value of props changes(if break point value does not change, component does not re-render even if screen size changes).The second one is to wrap useWindowDimensions for debounce to prevent re-rendering by size swapping for a very short amount of time by useWindowDimensions's bug.
Here is an example of my second solution.
```typescript
import { useEffect, useRef, useState } from "react"
import { Dimensions, useWindowDimensions } from "react-native"
const debounceTime = 1000
export const useDebouncedWindowDimensions = () => {
const timerRef = useRef | null>(null)
const [debouncedScreen, setDebouncedScreen] = useState(
Dimensions.get("screen")
)
const screen = useWindowDimensions()
useEffect(() => {
if (timerRef.current) {
clearTimeout(timerRef.current)
}
timerRef.current = setTimeout(() => {
setDebouncedScreen(screen)
}, debounceTime)
}, [screen])
return debouncedScreen
}
```
I love NativeBase, this library is giving me great development experience but this problem is so serious that I'm thinking about stopping using NativeBase.
Hope this problem gets resolved as soon as possible.
Contributor guide
Assessment
This issue has not been assessed yet.