What happened?
Uniwind Pro's View wrapper picks its rendered component from the current props on every render. In this reproduction, a defined accessibilityState renders RNView, while undefined renders AccessibleView, which is unstable_NativeView on React Native 0.86.
When the prop changes between those states, React sees a different element type at the same position and replaces the view. The key and position stay the same, but child effects clean up and run again, local state is lost, and native children are recreated.
We hit this with an expo-image inside the view. When image preparation finished and accessibilityState changed to undefined, the tile remounted, expo-image emitted onLoadStart again, and the image was blank for one frame. Plain React Native View updates in place.
Text has the same root issue. Its choice between AccessibleText and RNText depends on current values such as numberOfLines, disabled, accessibility and press props, and the shape of children.
Expected: changing these props updates the existing component and preserves its subtree.
Actual: Uniwind changes the rendered component type and remounts the subtree.
The rendered element type should stay stable across updates while preserving React Native's prop and accessibility handling.
Reproduced on uniwind-pro 1.6.0. I also checked the shipped 1.7.0 package, and the same prop-dependent branches are still present in View.tsx and Text.tsx.
Steps to Reproduce
import { useEffect, useState } from 'react'
import { Text, View } from 'react-native'
function Probe() {
useEffect(() => {
console.log('[probe] mount')
return () => console.log('[probe] unmount')
}, [])
return null
}
export default function Repro() {
const [busy, setBusy] = useState(true)
useEffect(() => {
const timeout = setTimeout(() => setBusy(false), 1000)
return () => clearTimeout(timeout)
}, [])
return (
<View accessibilityState={busy ? { busy: true } : undefined}>
<Probe />
<Text>{busy ? 'busy' : 'idle'}</Text>
</View>
)
}
- Run this through the normal Uniwind Pro Metro resolver.
- Observe
[probe] mount after the first render.
- After one second, observe
[probe] unmount followed by another [probe] mount.
- Expected: the probe mounts once because only a prop value changed.
- As a control, use
accessibilityState={{ busy }}. The extra unmount and mount no longer occur.
- Plain React Native without the Uniwind resolver also mounts the probe only once.
Snack or Repository Link (Optional)
No response
Uniwind version
uniwind-pro 1.6.0, installed as "uniwind": "npm:uniwind-pro@^1.6.0". Same wrapper code checked in 1.7.0.
React Native Version
0.86.3
Platforms
iOS
Expo
Yes
Additional information 〰
What happened?
Uniwind Pro's
Viewwrapper picks its rendered component from the current props on every render. In this reproduction, a definedaccessibilityStaterendersRNView, whileundefinedrendersAccessibleView, which isunstable_NativeViewon React Native 0.86.When the prop changes between those states, React sees a different element type at the same position and replaces the view. The key and position stay the same, but child effects clean up and run again, local state is lost, and native children are recreated.
We hit this with an
expo-imageinside the view. When image preparation finished andaccessibilityStatechanged toundefined, the tile remounted,expo-imageemittedonLoadStartagain, and the image was blank for one frame. Plain React NativeViewupdates in place.Texthas the same root issue. Its choice betweenAccessibleTextandRNTextdepends on current values such asnumberOfLines,disabled, accessibility and press props, and the shape ofchildren.Expected: changing these props updates the existing component and preserves its subtree.
Actual: Uniwind changes the rendered component type and remounts the subtree.
The rendered element type should stay stable across updates while preserving React Native's prop and accessibility handling.
Reproduced on
uniwind-pro1.6.0. I also checked the shipped 1.7.0 package, and the same prop-dependent branches are still present inView.tsxandText.tsx.Steps to Reproduce
[probe] mountafter the first render.[probe] unmountfollowed by another[probe] mount.accessibilityState={{ busy }}. The extra unmount and mount no longer occur.Snack or Repository Link (Optional)
No response
Uniwind version
uniwind-pro 1.6.0, installed as "uniwind": "npm:uniwind-pro@^1.6.0". Same wrapper code checked in 1.7.0.
React Native Version
0.86.3
Platforms
iOS
Expo
Yes
Additional information 〰