Skip to content

How do I reference a styled-component that is a functional component?

This is the most basic example I could think of:

import React from 'react';
import {
  css,
} from 'styled-components';

const Foo = (props) => {
  console.log(props);

  const {
    children,
  } = props;

  return <div {...props}>{children}</div>;
};

export default () => {
  return <div
    css={css`
      ${Foo} {
        background: #f00;
      }
    `}
  >
    <Foo>FOO</Foo>
  </div>;
};

In this example, I want to style Foo component that is a descendent of div.

I would expect the resulting markup to look something like:

<div class="test__Foo-wusfqk-0 hNfawX">FOO</div>

However, instead it is simply:

<div>FOO</div>

It seems like no styling is applied anywhere.

Furthermore, the component Foo is rendered only once, but it is invoked twice, with different parameters:

{children: {…}, theme: {…}}
  children: {$$typeof: Symbol(react.element), key: null, ref: null, props: {…}, type: ƒ, …}
  theme: {}

{children: "FOO"}

I should mention that I tried:

// @flow

import React from 'react';
import styled, {
  css,
} from 'styled-components';

const Foo = styled((props) => {
  const {
    className,
    children,
  } = props;

  return <div className={className}>{children}</div>;
});

export default () => {
  return <div
    css={css`
      ${Foo} {
        background: #f00;
      }
    `}
  >
    <Foo>FOO</Foo>
  </div>;
};


However, when executing this code in I am getting the following error:

The component Styled(Component) with the id of “sc-dlnjPT” 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.

The component Styled(Component) with the id of “sc-hKFyIo” 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.

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

which does not make much sense given the subject code snippet.

Answer

The main issue is that <Foo /> is not a styled component its a functional component

I think you would need to do

const Foo = styled.div`
    background: #f00;
`

Then you can change the style of Foo using css and the $ refrence

The reason your code does not work is the following

This behaviour is only supported within the context of Styled Components: attempting to mount B in the following example will fail because component Foo is an instance of React.Component not a Styled Component.

const Foo = () => <div> </div>

const B = styled.div`
  ${Foo} {
  }
`

However, wrapping Foo in a styled() factory makes it eligible for interpolation — just make sure the wrapped component passes along className.

const Foo = (props) => {
  console.log(props);

  const {
    children,
  } = props;

  return <div className="Test-Class" {...props}>{children}</div>;
};

const StyledFoo = styled(Foo)``

const Main = styled.div`
  ${StyledFoo} {
    background: #f00;
  }
`

Code Sandbox

import { render } from "react-dom";
import React from "react";
import styled from "styled-components";

const Foo = (props) => {
  const { className, children } = props;

  return <div className={className}>{children}</div>;
};

const Bar = styled(Foo)``;

const Main = styled.div`
  ${Bar} {
    background-color: #000;
    color: #fff;
  }
`;
const App = () => {
  return (
    <Main>
      {" "}
      <Bar>Hello </Bar>{" "}
    </Main>
  );
};

render(<App />, document.getElementById("root"));

https://codesandbox.io/s/styled-components-forked-5s201?file=/index.js