Search code examples
reactjsstyled-componentskeyframe

react styled component created dynamically


I am new to styled Components from react and I am having trouble creating dynamically a clock with has an initial degree for minutes(minute degrees) and an initial degree for hours (hourDegrees). image of my project

This is so far what I have achieved, but I get the following message:

Keyframes.js:20 The component styled.div with the id of "..." 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.

APP CODE

function App() {

  return (
    <div className="App">
      <main>
        <div className="clock-wrap">
          <section className="firstMinute">
            {numbers[0].map((coord, index) => {
              return (
                <Clock
                  key={index}
                  hourDegrees={coord[0]}
                  minuteDegrees={coord[1]}
                />
              );
            })}
          </section>

          <section className="secondMinute">
            {numbers[1].map((coord, index) => {
              return (
                <Clock
                  key={index}
                  hourDegrees={coord[0]}
                  minuteDegrees={coord[1]}
                />
              );
            })}
          </section>
        </div>
      </main>
    </div>
  );
}

But I can't solve this issue as, from what I understand, I have created separated components with the info passed as props.

import styled from 'styled-components'
    
   export default function Clock ({ minuteDegrees, hourDegrees, index}) { 

const finalHourDegrees = Number(hourDegrees + 360)
const finalMinuteDegrees = Number(minuteDegrees + 360)

  const StyledClock = styled.div`
  width: 10vh;
  `

  //hour
  const animationHour = keyframes`
  from {
    transform: rotate(${props => props.hourDegrees}deg);
  }
  to {
    transform: rotate(${finalHourDegrees}deg);
  }
  `
  const HourStyled = styled.div`
    animation: ${animationHour} 4s ease-out infinite;
  `


  //minutes
  const animationMinute = keyframes`
  from {
    transform: rotate(${props => props.minuteDegrees}deg);
  }
  to {
    transform: rotate(${finalMinuteDegrees}deg);
  }
  `


  const MinuteStyled = styled.div`
    
    animation: ${animationMinute} 4s ease-out infinite;
  `

return(
    <StyledClock className={index}>
      <HourStyled className={hourDegrees} key={index} hourDegrees={hourDegrees}/>
      <MinuteStyled className={minuteDegrees} key={index} minuteDegrees={minuteDegrees}/>
    </StyledClock>
)

}

Thanks a lot beforehand!


Solution

  • You can create StyledClock or MinuteStyled styled-components outside the target component. Also, you can send props to the styled components if needed.

    UPDATED I forked your code below and updated by using a callback function for the keyframes to pass the dynamic degrees codesandbox

    const StyledComponent = styled.div`
      background: ${props => props.background};
    `;
    

    Clock

    const StyledClock = styled.div`
      width: 6vw;
    `;
    
    export default function Clock({ minuteDegrees, hourDegrees, index }) {
      return (
        <StyledClock className={index}>
          <Hours index={index} hourDegrees={hourDegrees} />
          <Minutes index={index} minuteDegrees={minuteDegrees} />
        </StyledClock>
      );
    }
    

    Minutes

    const animationMinute = keyframes`
    from {
      transform: rotate(${(props) => props.minuteDegrees}deg);
    }
    to {
      transform: rotate(${(props) => props.finalMinuteDegrees}deg);
    }
    `;
    
    const MinuteStyled = styled.div`
      animation: ${animationMinute} 4s ease-out infinite;
    `;
    
    export default function Minutes({ minuteDegrees, index }) {
      const finalMinuteDegrees = Number(minuteDegrees + 360);
    
      return (
        <MinuteStyled
          className={minuteDegrees}
          key={index}
          minuteDegrees={minuteDegrees}
          finalMinuteDegrees={finalMinuteDegrees}
        />
      );
    }