Search code examples
reactjsgatsbystyled-components

React does not recognize the X prop on a DOM element


I am beginner developer and I am working on react (gatsby, TS, styled components) project. I am getting this error:

"React does not recognize the isOpen prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase isopen instead. If you accidentally passed it from a parent component, remove it from the DOM element."

export const Navigation = () => {
      const [isNavigationOpen, setIsNavigationOpen] = useState(false);
      const { isTablet } = useQuery();
    
      const showNavbar = () => {
        setIsNavigationOpen((previousState) => !previousState);
      };
    
      const renderElement = isTablet ? (
        <>
          <SvgStyled
            src='bars_icon'
            isOpen={isNavigationOpen}
            onClick={showNavbar}
          />
          <MobileNavigation isOpen={isNavigationOpen}>
            {NAVIGATION_DATA.map(({ id, url, text }) => (
              <LinkMobile key={id} to={url}>
                <ExtraSmallParagraph>{text}</ExtraSmallParagraph>
              </LinkMobile>
            ))}
          </MobileNavigation>
        </>
      ) : (
        <FlexWrapper>
          {NAVIGATION_DATA.map(({ id, url, text }) => (
            <LinkDekstop key={id} to={url}>
              <ExtraSmallParagraph>{text}</ExtraSmallParagraph>
            </LinkDekstop>
          ))}
        </FlexWrapper>
      );
    
      return renderElement;
    };

I am sure that I am missing some fundamental react stuff or something. Maybe someone could help me and explain the reason of this error.


Solution

  • When this happens it is because all props passed to the styled component are then also passed down to the DOM element that you are styling.

    You've likely a component that looks like the following:

    const SvgStyled = styled(SVG)<{ isOpen: boolean }>`
      // your CSS and logic referencing the `isOpen` prop
    `;
    

    To resolve this issue you refactor the styled component definition and explicitly pass only the props you want to the element being styled. Use an anonymous function component and destructure the prop you don't want to pass on to the DOM element, and spread the rest of the props. This ensures the className prop that styled-components is creating a CSS class for is passed through.

    Example:

    interface SvgStyledProps {
      className?: string,
      isOpen: boolean,
    }
    
    const SvgStyled = styled(({ isOpen, ...props}) => (
      <Svg {...props} />
    ))<SvgStyledProps>`
      // your CSS and logic referencing the `isOpen` prop
    `;
    

    For any other Typescript specifics/caveats with styled-components see docs.