reactjs - Utöka en React Styled-komponent


Jag kör version 5 av Styled Components och har vissa problem med att utöka en stylad komponent. Jag kommer att visa koden nedan.

Jag har en Heading-komponent som returnerar en React.FC som innehåller en StyledHeading. Sedan, i en annan fil, försöker jag utöka Heading. Men när jag gör detta verkar Heading-komponenten inte ens köras. Jag satte en konsollog i komponenten och den renderas inte.

Rubrik

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

import { font, fontSize, color, breakpoint } from 'theme';

interface Props {
  as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
  appearAs?: 'h1' | 'h1-jumbo' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
  align?: 'left' | 'center' | 'right';
  className?: string;
}

const Heading: React.FC<Props> = ({ as, appearAs = as, align = 'left', className, children }) => {
  const jumbo = appearAs === 'h1-jumbo';

  console.log('in heading'); // Runs when not extending, doesn't run when extending

  return (
    <StyledHeading as={as} appearAs={appearAs} align={align} jumbo={jumbo} className={className}>
      {children}
    </StyledHeading>
  );
};

const H1Styles = css<Props & { jumbo?: boolean }>`
  font-size: ${({ jumbo }) => (jumbo ? fontSize('xl') : fontSize('lg'))};
  text-align: ${({ jumbo, align }) => (jumbo ? 'center' : align)};

  @media (max-width: ${breakpoint('sm')}) {
    font-size: ${({ jumbo }) => jumbo && fontSize('lg')};
  }
`;

const StyledHeading = styled.div<Props & { jumbo?: boolean }>`
  font-family: ${font('bold')};
  line-height: 1.25;
  margin: 0;
  text-align: ${({ align }) => align};
  white-space: pre-wrap;

  ${({ appearAs }) => appearAs === 'h1' && H1Styles}
  ${({ appearAs }) => appearAs === 'h1-jumbo' && H1Styles}
`;

export default Heading;

Användning

// Renders an H2 but doesn't process appearAs or run console log
<StyledHeading as="h2" appearAs="h1-jumbo">TEST</StyledHeading>

// Renders an H2, appearAs works, and console log runs
<Heading as="h2" appearAs="h1-jumbo>TEST>/Heading>

const StyledHeading = styled(Heading)`margin-bottom: 1000px;`;

Alla råd skulle vara fantastiska eftersom jag just nu känner mig som vid en vägg. Tack!

Svar #1

Det är därför att din StyledHeading omsluter en annan komponent och med det behöver du använda forwardedAs istället för as, som:

<StyledHeading forwardedAs="h2" appearAs="h1-jumbo">
   TEST
</StyledHeading>

<Heading as="h2" appearAs="h1-jumbo">
   TEST
</Heading>

Och för att koden ovan ska fungera behöver du göra några ändringar i Props-gränssnittet samt i Heading-komponenten:

export interface Props {
  as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
  forwardedAs?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
  appearAs?: "h1" | "h1-jumbo" | "h2" | "h3" | "h4" | "h5" | "h6";
  align?: "left" | "center" | "right";
  className?: string;
}

const Heading: React.FC<Props> = ({
  as,
  forwardedAs,
  appearAs = as || forwardedAs,
  align = "left",
  className,
  children,
}) => {
  const jumbo = appearAs === "h1-jumbo";

  console.log("in heading"); // Runs when not extending, doesn't run when extending

  return (
    <StyledHeading
      as={as}
      forwardedAs={forwardedAs}
      appearAs={appearAs}
      align={align}
      jumbo={jumbo}
      className={className}
    >
      {children}
    </StyledHeading>
  );
};

*Som du kan se har jag satt as och forwardedAs som valfri egenskap (Eftersom jag inte vet hur komponenten ska bete sig, är det bara ett exempel).

Du kan också kolla på det här kodexemplet som jag gjorde (Om du klickar för att uppdatera URL-exemplet, kommer du att se komponenten loggas två gånger).

Och slutligen kan du läsa mer om detta här.