Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

styled-components: Extend existing component with additional prop for styling

I'm using styled-components to override styling from an existing component, in this case ToggleButton from material ui. However I want my new component to have one additional property (hasMargin) that controls the style:

import {ToggleButton} from "@material-ui/lab";
import styled, {css} from "styled-components";

const StyledToggleButton = styled(ToggleButton)<{ hasMargin?: boolean }>`
  && {
    color: red;

    ${props => props.hasMargin &&
      css`
          margin: 10px;
      `}
   }
`;

My intention is that StyledToggleButton behaves exactly like ToggleButton but has red color and can be called with an additional property hasMargin to turn on the margin css. I want to call it like this:

    <StyledToggleButton
      value={""} // ToggleButton prop
      size={"small"} // ToggleButton prop
      hasMargin={true} // My prop from StyledToggleButton
    >
      click
    </StyledToggleButton>

But if I do it like this, in the browser console I get:

Warning: React does not recognize the `hasMargin` prop on a DOM element.

This is because StyledToggleButton seems to also pass hasMargin further to ToggleButton and ToggleButton of course can't and shouldn't deal with that (passing it down to the DOM element where it makes no sense). What is the best way to rewrite my code, so hasMargin is only processed by StyledToggleButton?

I've made a codesandbox to illustrate the issue. Thank you!

like image 716
Giraphi Avatar asked Jan 25 '23 11:01

Giraphi


1 Answers

This is exactly what transient props are for.

All you need to do is prefix the prop with a $ and styled-components won't pass the prop to the underlying DOM element.

// Note the $ prefix in the prop name             👇
const StyledToggleButton = styled(ToggleButton)<{ $hasMargin?: boolean }>`
  && {
    color: red;

    // Just use the prop as normal
    ${(props) =>
      props.$hasMargin &&
      css`
        margin: 10px;
      `}
  }
`;

<StyledToggleButton
  value={""}
  size={"small"}
  {/* Assign the prop as normal */}
  $hasMargin={true}
>
  click
</StyledToggleButton>;

Here's your updated Codesandbox link with that error gone.

like image 159
Aron Avatar answered Jan 27 '23 01:01

Aron