故事书:在 .attrs 之后不使用反引号时,对象作为 React 子对象无效

Storybook: Objects are not valid as a React child when not using backticks after .attrs

我有以下简单的styled-component

const Button = styled.bytton.attrs(({primary}) => ({
  className: primary ? 'something' : 'something-else'
})

现在出于某种原因,除非我在 ed 中附加反引号,例如:

const Button = styled.bytton.attrs(({primary}) => ({
  className: primary ? 'something' : 'something-else'
})`` // here

我会从故事书中得到一个错误:

Objects are not valid as a React child (found: object with keys {$$typeof, render, attrs, >componentStyle, displayName, foldedComponentIds, styledComponentId, target, withComponent, >warnTooManyClasses, toString}). If you meant to render a collection of children, use an array >instead.

理想情况下,我想避免在代码库中放置随机反引号只是为了抑制错误...

.attrs 用于重建组件的道具(使用默认值或一些操作)以用于正常样式。

const Button = styled.button.attrs(props => ({
  layoutSize: props.size || '1em',
}))`
  margin: ${props => props.layoutSize};
  padding: ${props => props.layoutSize};
  ...
`

参考:when to use attrs

的文档

如果我们只想使用道具来做造型,我们可以不用.attrs

const Button = styled.button`
  margin: ${props => props.marginSize || '1em'};
  padding: ${props => props.paddingSize || '2em'};
  ...
`

如果您使用 styled-components api 的全部目的是创建共享围绕切换类名的逻辑的通用组件,您可能只想创建一个更高阶的组件。

function withProps(Component, propSetter) {
  return (props) => {
    const additionalProps = propSetter(props)
    return <Component {...props} {...additionalProps} />
  }
}

const Button = withProps('button', ({ primary }) => ({
  className: primary ? 'something' : 'something-else'
})

但是要给出原始问题的上下文:

提到的反引号并不像看起来那么随意。当您看到它们是空的时,它们可能会感到奇怪,但它们确实有其用途。要了解它们的用途,可能更容易了解当反引号或标记的模板文字被编译为常规 JavaScript.

时实际发生的情况
// Before
styled.button`
  color: green;
`

// After
styled.button(['color: green;'])

如您所见,字符串被传递到 return 从 styled.button 编辑的函数,styled.attrs return 相同的函数。现在上面的例子并没有充分利用反引号的力量。真正的力量来自函数调用。

// Before
styled.button`
  color: ${props => props.theme.color};
`

// After
styled.button(['color: ', ';'], props => props.theme.color)

如您所见,它已将模板与输入分开。函数的第一个参数是模板,后面的参数是数组中每个部分之后的输入。这就是带样式的组件如何传递 props 以在组件中执行特殊操作。

styled.buttonstyled.button.attrs() 都是 return 以这种方式使用标记的模板文字调用的函数。如果他们 return 编辑了一个可渲染的 React 组件,那么你根本无法提供 css。

当您尝试在没有反引号的情况下呈现某些内容时,您在 Button 中拥有的值是一个对象,其中包含准备好创建组件的信息。在您通过 () 或 `` 调用该对象之前,您将没有可以渲染的组件。

如果反引号太奇怪,那么用 () 替换它们可能会更舒服?或者你可以考虑创建一个包装函数或其他东西来确保它们总是被调用。