0

I have been playing around with styled-components and conditional rendering for a couple of days now and i have noticed some animation lag because of this i am not sure if it is actually related to styled-components or something else this is my button component can you please check if these checks are too heavy ? or could i have something else affecting the performance ?

export const StyledButton = styled.button`
  cursor: pointer;
  border-radius: ${borderRadius};
  outline: none;

  // inputs: color, outlined

  // default
  border: 1px solid transparent;
  color: ${({ theme, color }) => !color && theme.buttonText};
  background-color: ${({ theme, color }) => !color && theme.buttonBackground};

  // regular
  color: ${({ color, outlined }) => !outlined && color && colors.white};
  background-color: ${({ color, outlined }) => !outlined && color};

  // outlined
  color: ${({ color, outlined }) => outlined && color};
  background-color: ${({ color, outlined }) => outlined && color && `transparent`};

  border-color: ${({ color }) => color};
  transition: background-color 350ms linear, color 350ms linear;

  svg {
    transition: stroke 350ms linear;
    // default
    stroke: ${({ theme, color }) => !color && theme.buttonText};
    // regular
    stroke: ${({ color, outlined }) => !outlined && color && colors.white};
    // outlined
    stroke: ${({ color, outlined }) => outlined && color};
  }

  * > * {
    transition: color 350ms linear;
    // default
    color: ${({ theme, color }) => !color && theme.buttonText};
    // regular
    color: ${({ color, outlined }) => !outlined && color && colors.white};
    // outlined
    color: ${({ color, outlined }) => outlined && color};
  }

  &:hover {
    // default
    color: ${({ theme, color }) => !color && theme.buttonBackground};
    background-color: ${({ theme, color }) => !color && theme.buttonText};

    // regular
    color: ${({ color, outlined }) => !outlined && color};
    background-color: ${({ color, outlined }) => !outlined && color && "transparent"};

    // outlined
    color: ${({ color, outlined }) => outlined && color && colors.white};
    background-color: ${({ color, outlined }) => outlined && color};

    svg {
      // default
      stroke: ${({ theme, color }) => !color && theme.buttonBackground};
      // regular
      stroke: ${({ color, outlined }) => !outlined && color};
      // outlined
      stroke: ${({ color, outlined }) => outlined && color && colors.white};
    }

    * > * {
      // default
      color: ${({ theme, color }) => !color && theme.buttonBackground};
      // regular
      color: ${({ color, outlined }) => !outlined && color};
      // outlined
      color: ${({ color, outlined }) => outlined && color && colors.white};
    }
  }
`;
Raffi
  • 699
  • 1
  • 8
  • 19
  • There are quite a bit of repetitive CSS properties being created and overridden. I'd suggest interpolating once per property and creating a prop hierarchy for each style: [for example](https://stackoverflow.com/questions/56047659/multiple-props-options-for-styled-components/56049471#56049471). Or, since you have three separate props `color`, `theme` and `outlined`, you'll have to use a single nested if/else statement with a property OR create three separate switch/case statements without a property. – Matt Carlotta Aug 14 '21 at 22:07
  • Here's an example of how you can interpolate per property: [example](https://github.com/mattcarlotta/SJSITAPP-Website/blob/main/src/components/Layout/Button/index.tsx#L56-L129). This approach should be a bit easier to accomplish with your 3 changing props. Also, I just noticed this: ```border-radius: ${borderRadius};```, which tells me you're either composing it or placing it within a functional component that re-renders. Both will cause performance issues. This component should be a standalone file. – Matt Carlotta Aug 14 '21 at 22:14
  • Great I will check your solution and now I am not sure why repeating myself like this haha, `borderRadius` is just a constant i am importing from a separate JS file that is not a component nor a function just a const, does this have any issues with performance ? – Raffi Aug 14 '21 at 23:13
  • 1
    Styled components doesn't handle string interpolating very well. Instead it expects a function within a property to return a string: ```border-radius: ${() => borderRadius}```. Ideally, this string would come from a `prop` (or a `theme` prop) or a `defaultProp` instead of a string variable defined outside of the component. – Matt Carlotta Aug 14 '21 at 23:26
  • 1
    If the `border-radius` is mostly the same for each component instantiation, I like to do something like this: ```border-radius: ${({ borderRadius }) => borderRadius || "10px"};```. This provides a default prop without using a `defaultProp` property, which is exactly what I did in the per property [example](https://github.com/mattcarlotta/SJSITAPP-Website/blob/main/src/components/Layout/Button/index.tsx#L80) – Matt Carlotta Aug 14 '21 at 23:31
  • great I completely understand what's happening and now my rendering and animations are a lot faster i would love it if you could post the answer for me to accept it – Raffi Aug 14 '21 at 23:40

0 Answers0