临时反应组件中的样式组件 [英] Styled components in a hoc react component
问题描述
我在 React 的 hoc 包装器中使用样式组件时遇到了两个问题.
I am having two issues with using styled components in a hoc wrapper in react.
- 组件被渲染,但没有背景色.
- 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
(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
,所以我们可以返回一个更进一步:
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屋!