react-nativesvgreact-native-svg

react-native-svg: LinearGradient doesn't change between components when given different colors


I have a component that generates a square linear gradient using react-native-svg. When I pass in different hue colors, it stays the same color.

Things I tried:

What am I missing?

Expo Snack: https://snack.expo.dev/@paulwongx/react-native-svg_color_stop_issue

Gradient.js

import * as React from 'react';
import Svg, { Defs, LinearGradient, Rect, Stop } from "react-native-svg";

export default function Gradient({hue}) {
  return (
        <Svg width={128} height={128} viewBox="0 0 24 24">
            <Defs>
                <LinearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
                    <Stop offset="0" stopColor={`hsl(${hue}, 100%, 74%)`} />
                    <Stop offset="1" stopColor={`hsl(${hue}, 100%, 55%)`} />
                </LinearGradient>
            </Defs>
            <Rect width="100%" height="100%" fill="url(#gradient)" />
        </Svg>
  );
}

App.js

import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Gradient from './Gradient';

export default function App() {
  return (
    <View style={{flexDirection: "row", flexWrap: "wrap"}}>
      <Gradient hue={20} />
      <Gradient hue={50} />
      <Gradient hue={100} />
      <Gradient hue={150} />
      <Gradient hue={200} />
      <Gradient hue={250} />
      <Gradient hue={300} />
      <Gradient hue={350} />
    </View>
  );
}

Output:

Code output: Eight squares with the same color gradient

Looking at the rendered code within Inspect Element, the components show different hues but they all render the same colors.

// first component
<stop offset="0" stop-color="hsl(20, 100%, 74%)"></stop>
<stop offset="1" stop-color="hsl(20, 100%, 55%)"></stop>

// last component
<stop offset="0" stop-color="hsl(350, 100%, 74%)"></stop>
<stop offset="1" stop-color="hsl(350, 100%, 55%)"></stop>

Solution

  • I think you have to give a unique id to the linear gradient. The problem is that the id is always the same.

    import * as React from 'react';
    import Svg, { Defs, LinearGradient, Rect, Stop } from "react-native-svg";
    
    export default function Gradient({hue, id}) {
      return (
            <Svg width={128} height={128} viewBox="0 0 24 24">
                <Defs>
                    <LinearGradient id={`gradient_${id}`} x1="0%" y1="0%" x2="100%" y2="100%">
                        <Stop offset="0" stopColor={`hsl(${hue}, 100%, 74%)`} />
                        <Stop offset="1" stopColor={`hsl(${hue}, 100%, 55%)`} />
                    </LinearGradient>
                </Defs>
                <Rect width="100%" height="100%" fill={`url(#gradient_${id})`} />
            </Svg>
      );
    }
    

    And then

    import * as React from 'react';
    import { Text, View, StyleSheet } from 'react-native';
    import Gradient from './Gradient';
    
    export default function App() {
      return (
        <View style={{flexDirection: "row", flexWrap: "wrap"}}>
          <Gradient hue={20} id="first" />
          <Gradient hue={50} id="second" />
        </View>
      );
    }