情感使用 css prop 和自定义组件

Sky*_*010 11 emotion typescript reactjs

在我的应用程序中,我有一个组件,我想使用外部的 css prop 对其进行样式设置。

function Component({css}:{css?: React.CSSProperties}) {
  // some stuff going on here
  return (
    <div
      css={{
        color: blue,
        ...css
      }}
    >
       // some stuff going on here
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

背景如下:我想Component在不同的场景中使用,我必须根据周围的布局来设置容器的样式。例如,flex、grid 或与某些组件结合使用时,我必须添加不同的边距。

现在,我希望能够从组件外部设置容器的样式,而不是为所有可能的场景引入许多道具。

例如,该组件的用法可以是:

function Layout() {
  return (
    // some other components
    <Component css={{margin: 12}}/>
    // some other components
  )
}
Run Code Online (Sandbox Code Playgroud)

或者

import {css} from "@emotion/react"

const style = css({margin: 12})

function Layout() {
  return (
    // some other components
    <Component css={style}/>
    // some other components
  )
}
Run Code Online (Sandbox Code Playgroud)

或者

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
  )
}
Run Code Online (Sandbox Code Playgroud)

我有以下问题:

  1. 如果我使用 css 作为 prop 名称(如上例所示),则不会应用样式。如果我将道具的名称更改为例如,newCss它会按预期工作
  2. React.CSSProperties不是处理情感 css prop 的所有可能性的正确 prop 类型。
  3. 如何将不同的 css prop 可能性(对象、列表)与 css prop 合并Component

小智 14

事实上,我们不需要使用额外的道具。正如 Ben Laniado 提到的,官方文件指出

任何接受 className 属性的组件或元素也可以使用 css 属性。

https://emotion.sh/docs/css-prop#use-the-css-prop

所以我们需要的是接受classNameandcss作为 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是完整的工作示例。
https://codesandbox.io/s/react-component-accepting-emotion-css-prop-wskbh?file=/src/App.tsx


dek*_*oss 1

实现此功能的正确方法是修改组件以接受额外的道具。这样,传递到组件中的 css prop 将与组件内的 css prop 合并。

function Component({prop1, prop2, propN, ...props}) {
  // some stuff going on here
  return (
    <div
      css={{
        color: blue,
      }}
      {...props}
    >
       // some stuff going on here
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

现在您可以在组件上使用其他样式,并且它将正确呈现。

function Layout() {
  return (
    // some other components
    <Component css={{marginTop: "1em"}}/>
    // some other components
  )
}
Run Code Online (Sandbox Code Playgroud)

该解决方案的副作用是任何额外的 prop 都将直接传递到采用 的组件内的 HTML 元素{...props}