Search code examples
javascriptreactjsstyled-componentscraco

Styled Component ReferenceError: Cannot access 'Component' before initialization


While Referencing another component in the styled Component I am getting this error

ReferenceError: Cannot access 'SiteHeader' before initialization

here is the code

//Common.ts

import styled from 'styled-components/macro';
import { SiteHeader } from '../Theme/Layout/Header';

export const Container = styled.div`
    padding: 0 15px;
    ${SiteHeader} & {
        padding-top: 20px;
        padding-bottom: 20px;
    }
`;

//header.tsx

import { Container } from '../../Styles/Common';
import styled from 'styled-components/macro';

export default function Header(): JSX.Element {
    return (
        <SiteHeader>
            <Container>
                {/*navigation*/}
            </Container>
        </SiteHeader>
    );
}

export const SiteHeader = styled.header`
    background: var(--green-kelp);
`;


Solution

  • It looks like the problem here is that there's a circular dependency; Common.ts is importing header.tsx, and header.tsx is importing Common.ts. As a result, the build tool isn't able to work out which file should be parsed first, and SiteHeader isn't defined when it parses Container. It's a JS issue more than a styled-components issue.

    The solution to this problem is to make sure imports only go in 1 direction. The easiest way to do this is to move SiteHeader into its own file:

    SiteHeader.js:

    const SiteHeader = styled.header`
        background: var(--green-kelp);
    `;
    
    export default SiteHeader
    

    Common:

    import { SiteHeader } from './SiteHeader';
    
    export const Container = styled.div`
        padding: 0 15px;
        ${SiteHeader} & {
            padding-top: 20px;
            padding-bottom: 20px;
        }
    `;
    

    Header:

    import styled from 'styled-components/macro';
    
    import SiteHeader from '../SiteHeader';
    import { Container } from '../../Styles/Common';
    
    export default function Header(): JSX.Element {
        return (
            <SiteHeader>
                <Container>
                    {/*navigation*/}
                </Container>
            </SiteHeader>
        );
    }