Description
On native, withUniwind spreads the original props — className included — through to the wrapped component after converting them:
// src/hoc/withUniwind.native.tsx (1.11.0)
return (
<Component
{...props} // still contains className / *ClassName props
{...generatedProps}
/>
)
This is the same class of bug that #614 reported and #615 fixed, but #615 only touched withUniwind.tsx (web) and its web tests — withUniwind.native.tsx still forwards the class props.
Why it matters on native
If the wrapped component is app-source and forwards unknown props onto a core react-native component (whose import Metro has rewritten to the uniwind className-aware version), the leaked className applies the styles a second time on a different node than the style prop produced by the HOC.
We hit this with a first-party Pressable that routes its style prop to an inner glass surface while spreading the rest of its props onto RN's Pressable: every pill/card rendered doubled — an outer capsule (from the leaked className on the rewritten inner Pressable) plus the inner styled surface (from the converted style). Components wrapped from node_modules are unaffected because their internals aren't rewritten, which makes the failure look app-specific and hard to attribute.
Repro sketch
// app-source component that forwards unknown props to core RN
const Card = ({ style, ...rest }: ViewProps) => (
<Pressable {...rest}> // Metro-rewritten, className-aware
<GlassSurface style={style} /> // HOC's converted style lands here
</Pressable>
)
const StyledCard = withUniwind(Card)
<StyledCard className="rounded-full bg-blue-600 px-5 py-2" />
// → styles applied on BOTH the outer Pressable and the GlassSurface
Expected
withUniwind (auto and manual modes) removes className / *ClassName / *ColorClassName input props after converting them, matching the web behavior after #615.
Workaround
A shim between withUniwind and the component that strips className from the spread:
const withUniwindAppSource = (Component) =>
withUniwind(({ className: _c, ...rest }) => <Component {...rest} />)
Environment
- uniwind 1.11.0 (free tier), React Native 0.85.3, Expo SDK 56, New Architecture
- Coexisting with react-native-unistyles 3.2.4 during an incremental migration (not related to the bug — the forwarding is visible in the HOC source regardless)
Description
On native,
withUniwindspreads the original props —classNameincluded — through to the wrapped component after converting them:This is the same class of bug that #614 reported and #615 fixed, but #615 only touched
withUniwind.tsx(web) and its web tests —withUniwind.native.tsxstill forwards the class props.Why it matters on native
If the wrapped component is app-source and forwards unknown props onto a core
react-nativecomponent (whose import Metro has rewritten to the uniwind className-aware version), the leakedclassNameapplies the styles a second time on a different node than thestyleprop produced by the HOC.We hit this with a first-party Pressable that routes its
styleprop to an inner glass surface while spreading the rest of its props onto RN'sPressable: every pill/card rendered doubled — an outer capsule (from the leakedclassNameon the rewritten inner Pressable) plus the inner styled surface (from the convertedstyle). Components wrapped fromnode_modulesare unaffected because their internals aren't rewritten, which makes the failure look app-specific and hard to attribute.Repro sketch
Expected
withUniwind(auto and manual modes) removesclassName/*ClassName/*ColorClassNameinput props after converting them, matching the web behavior after #615.Workaround
A shim between
withUniwindand the component that stripsclassNamefrom the spread:Environment