Search code examples
reactjssvgstyled-components

svg spinner created with styled components sharing same color


I'm playing around with styled-components and trying to create a svg circle spinner component. Everything is great except when I try to use the component multiple times in same page then every component is using the same strokeColor from the last one. The other props strokeWidth is working fine though.

import React from "react";
import ReactDOM from "react-dom";

import Spinner from "./Spinner";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <Spinner strokeColor="#000000" strokeWidth={2} />
      <Spinner strokeColor="red" strokeWidth={1} />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

What am I missing here?

Here's the codesandbox demo link: https://codesandbox.io/s/pyo8kox787


Solution

  • The problem I see is that you've created your keyframes as regular css and not with styled-components keyframes helper.
    From the styled-components docs:

    CSS animations with @keyframes aren't scoped to a single component but you still don't want them to be global to avoid name collisions. This is why we export a keyframes helper which will generate a unique instance that you can use throughout your app

    As for what I can tell, the keyframes is created for the last component being rendered as they aren't scoped to the component. The fix is using the keyframes helper like this:

    import styled, {keyframes} from "styled-components";
    
    const colorKeyFrames = keyframes`
    0% {
          stroke: ${props => props.color || "#ffffff"};
        }
        40% {
          stroke: ${props => props.color || "#ffffff"};
        }
        66% {
          stroke: ${props => props.color || "#ffffff"};
        }
        80%,
        90% {
          stroke: ${props => props.color || "#ffffff"};
        }
    `;
    

    And a fix for your sandbox here.
    Keep in mind, you'll need to fix it for every keyframes you have there.