临时反应组件中的样式组件 [英] Styled components in a hoc react component

查看:28
本文介绍了临时反应组件中的样式组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 React 的 hoc 包装器中使用样式组件时遇到了两个问题.

I am having two issues with using styled components in a hoc wrapper in react.

  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

I have made a code sandbox to illustrate the issue: https://codesandbox.io/s/styled-hoc-xgduo?file=/src/Components/Node/Node.tsx

推荐答案

解释样式错误

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

Style Errors Explained

@Mosh Feu's comment pointed me in the right direction.

您可以将样式添加到已设置样式的组件,并且您可以添加样式到自定义组件,但这两件事的工作方式不同.你有一条贯穿这两种类型的链条,所以事情正在丢失.

You can add styles to an already styled component and you can add styles to a custom component, but those two things work differently. You have a chain that goes through both types, so things are getting lost.

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

When you call withColors(Node) what this is doing is passing a generated className prop to Node. But your custom component Node never does anything with this prop, so the style is never applied.

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

The styled method works perfectly on all of your own or any third-party component, as long as they attach the passed className prop to a DOM element.

已修复样式错误

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

Style Errors Fixed

If we edit Node to use this className, we get the color!

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) 的道具时遇到错误,其中显示就像一堆疯狂的废话:

TS Errors Explained

As far as the typescript errors are concerned, you're getting an error about assigning your props T to the props of a styled component (ComponentWithAddedColors), which shows up as a bunch of crazy nonsense:

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

(props: (Pick<Pick<(PropsWithoutRef & RefAttributes<Component<T, any, any>>) | (PropsWithRef<PropsWithChildren> & {}), Exclude<...> | ... 1 more ... | Exclude<...>> & Partial<...>, Exclude<...> | ... 1 more ... | Exclude<...>> & { ...; } & { ...; }) | (Pick<...> & ... 2 more ... & { ...; })): ReactElement<...>

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

This is mainly because of ref forwarding through the ForwardRefExoticComponent type.

但是我们可以逆向使用实用程序类型从组件类型中获取预期的 props 类型:

But we can work backwards to get the expected props type from the component type using a utility type:

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

所以 ComponentWithAddedColors 有 props PropsOf.我们可以使用它,但我们也知道 ComponentWithAddedColors 的类型为 StyledComponent, any, {}, never>,所以我们可以返回一个更进一步:

So ComponentWithAddedColors has props PropsOf<typeof ComponentWithAddedColors>. We could use that, but we also know that ComponentWithAddedColors has type StyledComponent<React.ComponentType<T>, any, {}, never>, so we can go back a step further:

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

所以 ComponentWithAddedColors 有 props StyledProps.

So ComponentWithAddedColors has props StyledProps<T>.

也就是说,所有这些都是不必要的,至少在您展示的示例中是这样.您将 ComponentWithAddedColors 的所有 props 传递给 ComponentWithAddedColors,因此 result 与组件本身是一回事.直接退货就行了.

That said, all of this is unnecessary, at least in the example you've shown. You are passing all of the props of ComponentWithAddedColors through to ComponentWithAddedColors, so result is the same thing as the component itself. Just return it directly.

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

这篇关于临时反应组件中的样式组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆