fix: new arch invalidate on mount/unmount (#2318)

# Summary

On iOS with the new architecture, when mounting or unmounting a
component, changes were not visible because `invalidate` wasn't called.
These changes override `mountChildComponentView` and
`unmountChildComponentView` to ensure that invalidate is called when
`RNSVGNode` is mounted or unmounted.

## Test Plan

`TestExample` app -> `MountUnmount` example 

```tsx
import React from 'react';
import {Button, Text, View} from 'react-native';
import {Rect, Svg} from 'react-native-svg';

export default () => {
  const [show, setShow] = React.useState(true);
  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Text>Blue rect is mounted: {show ? 'true' : 'false'}</Text>

      <Svg height="300" width="300">
        {show ? (
          <Rect x="100" y="100" width="100" height="100" fill="blue" />
        ) : null}
      </Svg>
      <Button title="Toggle" onPress={() => setShow(!show)} />
    </View>
  );
};
```


https://github.com/software-mansion/react-native-svg/assets/39670088/0eaf9a61-b47b-4f89-a7c7-a67375e2e63e


https://github.com/software-mansion/react-native-svg/assets/39670088/709feedf-63c1-47d7-b799-f3899278fe77


## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
This commit is contained in:
Jakub Grzywacz
2024-07-01 16:21:18 +02:00
committed by GitHub
parent fe48dfb238
commit e16a1519ba
3 changed files with 43 additions and 0 deletions
+1
View File
@@ -3,6 +3,7 @@ import React from 'react';
import ColorTest from './src/ColorTest'; import ColorTest from './src/ColorTest';
import PointerEventsBoxNone from './src/PointerEventsBoxNone'; import PointerEventsBoxNone from './src/PointerEventsBoxNone';
import MountUnmount from './src/MountUnmount';
import Test1374 from './src/Test1374'; import Test1374 from './src/Test1374';
import Test1442 from './src/Test1442'; import Test1442 from './src/Test1442';
import Test1451 from './src/Test1451'; import Test1451 from './src/Test1451';
+28
View File
@@ -0,0 +1,28 @@
import React from 'react';
import {Button, Text, View} from 'react-native';
import {Rect, Svg} from 'react-native-svg';
export default () => {
const [show, setShow] = React.useState(true);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Blue rect is mounted: {show ? 'true' : 'false'}</Text>
<Svg height="300" width="300">
<Rect
x="0"
y="0"
width="300"
height="300"
fill="transparent"
stroke="red"
strokeWidth={3}
/>
{show ? (
<Rect x="100" y="100" width="100" height="100" fill="blue" />
) : null}
</Svg>
<Button title="Toggle" onPress={() => setShow(!show)} />
</View>
);
};
+14
View File
@@ -59,6 +59,20 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
[self invalidate]; [self invalidate];
} }
#ifdef RCT_NEW_ARCH_ENABLED
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
{
[super mountChildComponentView:childComponentView index:index];
[self invalidate];
}
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
{
[super unmountChildComponentView:childComponentView index:index];
[self invalidate];
}
#endif
- (void)didUpdateReactSubviews - (void)didUpdateReactSubviews
{ {
// Do nothing, as subviews are inserted by insertReactSubview: // Do nothing, as subviews are inserted by insertReactSubview: