emotion 使用 css prop 和自定义组件
emotion use css prop with custom components
在我的应用程序中,我有一个组件,我想使用外部的 css 道具来设置样式。
function Component({css}:{css?: React.CSSProperties}) {
// some stuff going on here
return (
<div
css={{
color: blue,
...css
}}
>
// some stuff going on here
</div>
)
}
背景如下:
我想在必须根据周围布局设置容器样式的不同场景中使用 Component
。例如。 flex、grid 或结合某些组件我必须添加不同的边距。
现在我希望能够从组件外部设置容器的样式,而不是为所有可能的场景引入许多道具。
例如该组件的用法可能是:
function Layout() {
return (
// some other components
<Component css={{margin: 12}}/>
// some other components
)
}
或
import {css} from "@emotion/react"
const style = css({margin: 12})
function Layout() {
return (
// some other components
<Component css={style}/>
// some other components
)
}
或
import {css} from "@emotion/react"
const style1 = css({margin: 12})
const style2 = css({color: 'red'})
function Layout() {
return (
// some other components
<Component css={[style1, style2]}/>
// some other components
)
}
我有以下问题:
- 如果我使用 css 作为道具名称(如上例所示),则不会应用该样式。如果我将道具的名称更改为例如
newCss
它按预期工作
React.CSSProperties
不是处理情绪所有可能性的正确道具类型 css 道具。
- 如何将不同的 css 道具可能性(对象、列表)与来自
Component
的 css 道具合并?
实现此功能的正确方法是修改组件以接受额外的道具。这样,传递到组件中的 css 属性将与组件中的属性合并。
function Component({prop1, prop2, propN, ...props}) {
// some stuff going on here
return (
<div
css={{
color: blue,
}}
{...props}
>
// some stuff going on here
</div>
)
}
现在您可以在您的组件上使用额外的样式,它会被正确呈现。
function Layout() {
return (
// some other components
<Component css={{marginTop: "1em"}}/>
// some other components
)
}
此解决方案的副作用是,任何额外的 prop 都将直接传递给采用 {...props}
的组件内的 HTML 元素。
事实上,我们不需要使用额外的道具。正如 Ben Laniado 所提到的,官方文档指出
Any component or element that accepts a className prop can also use the css prop.
https://emotion.sh/docs/css-prop#use-the-css-prop
所以我们需要接受 className
和 css
作为 props 并将 className
添加到组件中。 (我们不需要组件 css
但类型需要它)
type ComponentProps = {
css?: SerializedStyles;
className?: string;
};
const Component: VFC<ComponentProps> = ({ className }) => {
return (
<div css={{ color: blue }} className={className}>
hello world
</div>
);
};
export default function App() {
return (
<div className="App">
<Component css={{ margin: 12 }} />
</div>
);
}
这是完整的工作示例。
https://codesandbox.io/s/react-component-accepting-emotion-css-prop-wskbh?file=/src/App.tsx
在我的应用程序中,我有一个组件,我想使用外部的 css 道具来设置样式。
function Component({css}:{css?: React.CSSProperties}) {
// some stuff going on here
return (
<div
css={{
color: blue,
...css
}}
>
// some stuff going on here
</div>
)
}
背景如下:
我想在必须根据周围布局设置容器样式的不同场景中使用 Component
。例如。 flex、grid 或结合某些组件我必须添加不同的边距。
现在我希望能够从组件外部设置容器的样式,而不是为所有可能的场景引入许多道具。
例如该组件的用法可能是:
function Layout() {
return (
// some other components
<Component css={{margin: 12}}/>
// some other components
)
}
或
import {css} from "@emotion/react"
const style = css({margin: 12})
function Layout() {
return (
// some other components
<Component css={style}/>
// some other components
)
}
或
import {css} from "@emotion/react"
const style1 = css({margin: 12})
const style2 = css({color: 'red'})
function Layout() {
return (
// some other components
<Component css={[style1, style2]}/>
// some other components
)
}
我有以下问题:
- 如果我使用 css 作为道具名称(如上例所示),则不会应用该样式。如果我将道具的名称更改为例如
newCss
它按预期工作 React.CSSProperties
不是处理情绪所有可能性的正确道具类型 css 道具。- 如何将不同的 css 道具可能性(对象、列表)与来自
Component
的 css 道具合并?
实现此功能的正确方法是修改组件以接受额外的道具。这样,传递到组件中的 css 属性将与组件中的属性合并。
function Component({prop1, prop2, propN, ...props}) {
// some stuff going on here
return (
<div
css={{
color: blue,
}}
{...props}
>
// some stuff going on here
</div>
)
}
现在您可以在您的组件上使用额外的样式,它会被正确呈现。
function Layout() {
return (
// some other components
<Component css={{marginTop: "1em"}}/>
// some other components
)
}
此解决方案的副作用是,任何额外的 prop 都将直接传递给采用 {...props}
的组件内的 HTML 元素。
事实上,我们不需要使用额外的道具。正如 Ben Laniado 所提到的,官方文档指出
Any component or element that accepts a className prop can also use the css prop.
https://emotion.sh/docs/css-prop#use-the-css-prop
所以我们需要接受 className
和 css
作为 props 并将 className
添加到组件中。 (我们不需要组件 css
但类型需要它)
type ComponentProps = {
css?: SerializedStyles;
className?: string;
};
const Component: VFC<ComponentProps> = ({ className }) => {
return (
<div css={{ color: blue }} className={className}>
hello world
</div>
);
};
export default function App() {
return (
<div className="App">
<Component css={{ margin: 12 }} />
</div>
);
}
这是完整的工作示例。
https://codesandbox.io/s/react-component-accepting-emotion-css-prop-wskbh?file=/src/App.tsx