Search code examples
javascriptreactjsstyled-components

How do I correctly use 'styled-components'?


I created a spinner for my application. It works in every way as intended. I am, however, getting a warning stating that I am using "Styled" in the wrong manner. I Attempted to convert the component into a class based component, but it did not work. I am 100% positive this is not the best way to create this component, but I am relatively new to React. The reason I am even using Styled-components is because of the ":after" being unavailable in JSX inline styling. I would be tremendously thankful for any advice anyone may have regarding this issue. I would assume there is a relatively simple solution to this, but I have not found it.

The component styled.div with the id of "sc-bdnylx" has been created dynamically. You may see this warning because you've called styled inside another component. To resolve this only create new StyledComponents outside of any render method and function component.

I call my Spinner with:

<Spinner additionalclasses='mr20' size='small' color='#39FF14' />

The code for the Spinner component:

import React from 'react'
import './spinner.css'
import styled from 'styled-components'

function Spinner(props) {
let wrapperStyles = {}
let spinnerStyles = {}

switch (props.size) {
    case 'extrasmall':
        wrapperStyles = { width: '20px', height: '20px' }
        spinnerStyles = { transform: `translateX(-38%) scale(0.25)` }
        break
    case 'small':
        wrapperStyles = { width: '40px', height: '40px' }
        spinnerStyles = { transform: `translateX(-25%) scale(0.5)` }
        break
    case 'medium':
        wrapperStyles = { width: '60px', height: '60px' }
        spinnerStyles = { transform: `translateX(-12.5%) scale(0.75)` }
        break
    case 'large':
        wrapperStyles = { width: '80px', height: '80px' }
        spinnerStyles = { transform: `translateX(-0%) scale(1)` }
        break
    case 'extralarge':
        wrapperStyles = { width: '120px', height: '120px' }
        spinnerStyles = { transform: `translateX(25%) scale(1.5)` }
        break
    case 'huge':
        wrapperStyles = { width: '240px', height: '240px' }
        spinnerStyles = { transform: `translateX(94%) scale(3)` }
        break
    default:
        wrapperStyles = {}
        spinnerStyles = {}
}

let color = props.color

const SpinnerDiv = styled.div`
    &:after {
        background: ${color};
    }
`

return (
    <div
        className={`spinner_wrapper ${props.additionalclasses}`}
        style={wrapperStyles}
    >
        <div className='spinner_container' style={spinnerStyles}>
            <div className='lds-spinner' style={{ color: `${color}` }}>
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
                <SpinnerDiv />
            </div>
        </div>
    </div>
)
}

export default Spinner

Solution

  • What you have to do is to move the SpinnerDiv styled component outside your functional component because it is being re-created everytime your component re-renders.

    And inside your render function you can pass props to the styled-component as you wanted to, like this:

    <SpinnerDiv color={/* a color */} />
    

    And then to use it in the styled component:

    const SpinnerDiv = styled.div`
        &:after {
            background: ${props => props.color};
        }
    `;
    

    Or even better, you can destructure props:

    const SpinnerDiv = styled.div`
        &:after {
            background: ${({ color }) => color};
        }
    `;