【问题标题】:Styled components in a hoc react component临时反应组件中的样式化组件
【发布时间】:2021-02-12 04:50:46
【问题描述】:

在 react 的 hoc 包装器中使用样式化组件有两个问题。

  1. 组件已渲染,但未使用背景颜色。
  2. ComponentWithAddedColors 不是有效的打字稿。不知道为什么。

谁能帮忙解决这个问题?

interface IProps {
  id: string;
  left: number;
  top: number;
}

export const Node: React.FC<IProps> = ({ id, left, top }) => {
  return (
    <Container left={left} top={top}>
      {id}
    </Container>
  );
};

function withColors<T>(Component: React.ComponentType<T>) {
  const bg = "hotpink";
  const ComponentWithAddedColors = styled(Component)`
    ${bg && `background: ${bg};`}
  `;
  const result: React.FC<T> = (props) => (
    <ComponentWithAddedColors {...props} />
  );
  return result;
}

const DraggableNode = withColors(Node);
export default DraggableNode;

我制作了一个代码沙箱来说明这个问题: https://codesandbox.io/s/styled-hoc-xgduo?file=/src/Components/Node/Node.tsx

【问题讨论】:

  • 这是因为 styled 函数只接受样式化组件 - 意思是,由 styled 创建的组件,就像在 their exampe 中一样。看到这个:codesandbox.io/s/styled-hoc-forked-wjb99?file=/src/Components/…
  • @MoshFeu 感谢您的反馈。你知道为什么还会出现打字稿错误吗?
  • @MoshFeu 我刚刚检查了类型定义文件的样式。它确实接受 JSX.IntrinsicElements 作为参数。问题在于文档底部的描述:“但是,将 A 包装在 styled() 工厂中使其符合插值条件 - 只需确保包装的组件通过 className。”

标签: reactjs typescript styled-components


【解决方案1】:

样式错误说明

@Mosh Feu 的评论为我指明了正确的方向。

您可以添加样式to an already styled component,也可以添加样式to a custom component,但这两者的工作方式不同。你有一条贯穿这两种类型的链,所以东西会丢失。

当您调用withColors(Node) 时,它所做的是将生成的className 属性传递给Node。但是你的自定义组件 Node 从来没有对这个 prop 做任何事情,所以这个样式永远不会被应用。

styled 方法在您自己或任何第三方组件上都能完美运行,只要它们将传递的 className 属性附加到 DOM 元素。

样式错误已修复

如果我们编辑Node 来使用这个className,我们就会得到颜色!

export const Node: React.FC<IProps & {className?: string}> = ({ id, left, top, className}) => {
  return (
    <Container left={left} top={top} className={className}>
      {id}
    </Container>
  );
};

TS 错误说明

就打字稿错误而言,您在将您的道具 T 分配给样式组件 (ComponentWithAddedColors) 的道具时遇到错误,这显示为一堆疯狂的废话:

(props: (Pick>) | (PropsWithRef & {}), Exclude<...> | ... 1 更多。 .. | 排除<...>> & 部分<...>, 排除<...> | ... 1 更多 ... | 排除<...>> & { ...; } & { ...; }) | (Pick<...> & ... 2 更多 ... & { ...; })): ReactElement<...>

这主要是因为通过ForwardRefExoticComponent类型的ref转发。

但是我们可以向后工作,使用实用程序类型从组件类型中获取预期的道具类型:

type PropsOf<T> = T extends React.ComponentType<infer P> ? P : never;

所以ComponentWithAddedColors 有道具PropsOf&lt;typeof ComponentWithAddedColors&gt;。我们可以使用它,但我们也知道ComponentWithAddedColors 的类型为StyledComponent&lt;React.ComponentType&lt;T&gt;, any, {}, never&gt;,所以我们可以更进一步:

type StyledProps<InitialProps> = PropsOf<StyledComponent<React.ComponentType<InitialProps>, any, {}, never>>

所以ComponentWithAddedColors 有道具StyledProps&lt;T&gt;

修复了 TS 错误

也就是说,所有这些都是不必要的,至少在您展示的示例中是这样。您将ComponentWithAddedColors 的所有道具传递给ComponentWithAddedColors,因此result 与组件本身相同。直接退货就好了。

function withColors<T>(Component: React.ComponentType<T>) {
  const bg = "hotpink";
  return styled(Component)`
    ${bg && `background: ${bg};`}
  `;
}

【讨论】:

猜你喜欢
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 2019-05-09
  • 2018-02-04
  • 1970-01-01
  • 2020-02-29
  • 2020-12-03
  • 1970-01-01
相关资源
最近更新 更多