Commit bc005aa
authored
fix(android): fix MaskView broken when enabling RN props 2.0 (#2948)
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect -->
# Summary
On android when enabling props 2.0 diffing in react-native:
```kt
override fun enablePropsUpdateReconciliationAndroid(): Boolean = true
override fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean = true
override fun enableExclusivePropsUpdateAndroid(): Boolean = true
```
the mounting layer will use `Props::getDiffProps()` to figure out what
props to supply to the native views:
https://github.com/facebook/react-native/blob/91702e50fe077ae73ab152da18719d6df98cb71f/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp#L314-L318
In RN-SVGs codegen specs we specify for mask the following:
https://github.com/software-mansion/react-native-svg/blob/52369e1a5a7cbc3e21e32adecba4839c8bf56e5b/src/fabric/MaskNativeComponent.ts#L77-L79
which will generate:
<img width="588" height="259" alt="Screenshot 2026-05-07 at 15 29 26"
src="https://github.com/user-attachments/assets/9f156262-96cb-43f8-b48f-d02458fad8dd"
/>
So you see that we specified `maskType` as optional, but on the c++
level the prop got as default value of `0`.
> There is a way to change this in codegen setting
[generateOptionalProperties](react/react-native#54724)
as option. However, for `Int32` values [its broken right now
unfortunately](react/react-native#55315).
[Making it also optional in the c++ props would've been the better fix
imo]
Now, the problem is that in JS we set the default `maskType={0}`:
https://github.com/software-mansion/react-native-svg/blob/52369e1a5a7cbc3e21e32adecba4839c8bf56e5b/src/elements/Mask.tsx#L61
https://github.com/software-mansion/react-native-svg/blob/52369e1a5a7cbc3e21e32adecba4839c8bf56e5b/src/lib/maskType.ts#L1-L3
_However,_ now when the mounting layer calls `getDiffProps` it will
compare our passed prop value of `maskType={0}` with the default value
`int maskType{0}`, and there will be no diff …:
<img width="726" height="253" alt="Screenshot 2026-05-07 at 15 36 57"
src="https://github.com/user-attachments/assets/e82f86a7-7430-4114-beb7-0493adf3fb1a"
/>
… so as there is no diff, the prop will never be dispatched to our
native component hence `setMaskType` will never be called:
https://github.com/software-mansion/react-native-svg/blob/51defd73d33a367c85b68b4007431347f049706b/android/src/main/java/com/horcrux/svg/MaskView.java#L93-L104
Which basically breaks the mask from working!
In general we need to make sure that assumed defaults (ie. maskType
default value 0) are reflected in the native component implementation,
and we shouldn't rely on prop setter functions being called for default
values.
Hence my fix here is to simply set the default value in the native view
:\)
## Test Plan
### What's required for testing (prerequisites)?
Try to set the feature flags i mentioned and then observe the issues
with mask component
### What are the steps to reproduce (after prerequisites)?
^
## Compatibility
| OS | Implemented |
| ------- | :---------: |
| iOS | ❌ |
| MacOS | ❌ |
| Android | ✅ |
| Web | ❌ |
## Checklist
<!-- Check completed item, when applicable, via: [X] -->
- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
- [x] I added a test for the API in the `__tests__` folder1 parent 21c4783 commit bc005aa
1 file changed
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| |||
0 commit comments