Description
When an SVG element (e.g. <Path>) uses the markerEnd prop, state changes that occur after mount do not cause the SVG to visually re-render on iOS. React processes the state update and re-renders the component tree correctly, but the SVG canvas never redraws — so any child element whose output depends on the updated state (e.g. a <Text> showing a counter) is stuck displaying the initial value.
Expected behavior: When state updates, the SVG should re-render and display the new values — e.g. the <Text> counter should advance from 0 to 1 after one second.
Actual behavior: The <Text> counter inside the SVG permanently shows 0. The state update fires (React processes it), but the SVG canvas never redraws to reflect it. The below reproduction is a trivial example, but it's a larger issue for us as we're building a whiteboard drawing application and this issue is preventing us from being able to allow users to draw paths with arrowheads in iOS as nothing is being re-rendered after the initial path is drawn.
Potential root cause (for maintainers):
|
- (void)setMarkerPath:(CGPathRef)markerPath |
|
{ |
|
if (_markerPath == markerPath) { |
|
return; |
|
} |
|
|
|
CGPathRelease(_markerPath); |
|
|
|
_markerPath = markerPath; |
|
[self invalidate]; |
|
} |
when we comment out
[self invalidate] when state changes a re-render is triggered and the updated counter is displayed.
Steps to reproduce
- Render a
<Svg> containing a <Defs>/<Marker> block and an element using the marker prop (e.g. marker="url(#selection)").
- Include a
<Text> inside the SVG that displays a state value.
- In a
useEffect, use setTimeout to update that state value once after 1 second.
- Run on iOS.
- Observe: the
<Text> inside the SVG shows 0 initially and never updates to 1, even after the timeout fires.
- Removing the
marker prop from the <Ellipse> causes the <Text> to update correctly.
Minimal reproduction:
Update ellipse example within this repo (apps/common/example/examples/Markers.tsx)
import React, { useEffect, useState } from 'react';
import { Circle, Defs, Ellipse, Marker, Svg, Text } from 'react-native-svg';
export default function EllipseExample() {
const [secondValue, setSecondValue] = useState(0);
useEffect(() => {
setTimeout(() => {
setSecondValue(v => v + 1);
}, 1000);
}, []);
return (
<Svg height="300" width="400">
<Defs>
<Marker
id="selection"
markerUnits="userSpaceOnUse"
refX="0"
refY="0"
orient="auto">
<Circle fill="#3a6cff" r={5} cx={0} cy={0} strokeWidth={1} stroke="white" />
</Marker>
</Defs>
{/* This text never updates from 0 to 1 when marker prop is present */}
<Text x={5} y={10} fill="black">{secondValue}</Text>
<Ellipse
cx="200" cy="170" rx="30%" ry="10%"
stroke="purple" strokeWidth="2" fill="yellow"
marker="url(#selection)"
/>
</Svg>
);
}
Note: Removing marker="url(#selection)" from the <Ellipse> causes the <Text> to correctly update to 1 after one second.
Snack or a link to a repository
https://github.com/rheidari/react-native-svg/blob/main/apps/common/example/examples/Markers.tsx#L15-L59
SVG version
15.15.4 (current version as defined in the package.json of this repo)
React Native version
^0.77.0 (current version as defined in the package.json of this repo)
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native
Architecture
Fabric (New Architecture)
Build type
Debug app & dev bundle
Device
iOS simulator
Device model
iPhone 17
Acknowledgements
Yes
Description
When an SVG element (e.g.
<Path>) uses themarkerEndprop, state changes that occur after mount do not cause the SVG to visually re-render on iOS. React processes the state update and re-renders the component tree correctly, but the SVG canvas never redraws — so any child element whose output depends on the updated state (e.g. a<Text>showing a counter) is stuck displaying the initial value.Expected behavior: When state updates, the SVG should re-render and display the new values — e.g. the
<Text>counter should advance from0to1after one second.Actual behavior: The
<Text>counter inside the SVG permanently shows0. The state update fires (React processes it), but the SVG canvas never redraws to reflect it. The below reproduction is a trivial example, but it's a larger issue for us as we're building a whiteboard drawing application and this issue is preventing us from being able to allow users to draw paths with arrowheads in iOS as nothing is being re-rendered after the initial path is drawn.Potential root cause (for maintainers):
react-native-svg/apple/RNSVGNode.mm
Lines 240 to 250 in 5b62c5d
[self invalidate]when state changes a re-render is triggered and the updated counter is displayed.Steps to reproduce
<Svg>containing a<Defs>/<Marker>block and an element using the marker prop (e.g.marker="url(#selection)").<Text>inside the SVG that displays a state value.useEffect, usesetTimeoutto update that state value once after 1 second.<Text>inside the SVG shows0initially and never updates to1, even after the timeout fires.markerprop from the<Ellipse>causes the<Text>to update correctly.Minimal reproduction:
Update ellipse example within this repo (
apps/common/example/examples/Markers.tsx)Note: Removing
marker="url(#selection)"from the<Ellipse>causes the<Text>to correctly update to1after one second.Snack or a link to a repository
https://github.com/rheidari/react-native-svg/blob/main/apps/common/example/examples/Markers.tsx#L15-L59
SVG version
15.15.4 (current version as defined in the package.json of this repo)
React Native version
^0.77.0 (current version as defined in the package.json of this repo)
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native
Architecture
Fabric (New Architecture)
Build type
Debug app & dev bundle
Device
iOS simulator
Device model
iPhone 17
Acknowledgements
Yes