2

我正在运行样式化组件的 v5,并且在扩展样式化组件时遇到了一些问题。我将在下面显示代码。

我有一个 Heading 组件,它返回一个包含 StyledHeading 的 React.FC。然后,在另一个文件中,我试图扩展 Heading. 但是,执行此操作时,标题组件甚至似乎都没有运行。我在组件中放置了一个控制台日志,但它没有呈现。

标题

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;

用法

// 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;`;

任何建议都会非常棒,因为我现在感觉很困难。谢谢!

4

1 回答 1

3

那是因为您的 StyledHeading 正在包装另一个组件,并且您需要使用它forwardedAs来代替as,例如:

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

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

对于上面的代码,您需要对Props界面和Heading组件进行一些更改:

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>
  );
};

*如您所见,我将asand设置forwardedAs为可选属性(因为我不知道组件的行为方式,这只是一个示例)。

此外,您可以检查我所做的此代码示例(如果您单击更新 url 示例,您将看到两次记录组件)。

最后,您可以在此处阅读更多相关信息。

于 2020-09-09T17:40:07.480 回答