首页 > 解决方案 > 故事书:在 .attrs 之后不使用反引号时,对象作为 React 子项无效

问题描述

我有以下简单的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

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

对象作为 React 子对象无效(发现:对象与键 {$$typeof, render, attrs, >componentStyle, displayName, foldedComponentIds, styledComponentId, target, withComponent, >warnTooManyClasses, toString})。如果您打算渲染一组子元素,请使用数组 > 而不是。

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

标签: javascriptreactjsstyled-componentsstorybook

解决方案


如果您使用 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;'])

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

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

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

如您所见,它已将模板与输入分开。函数的第一个参数是模板,后面的参数是数组中每个部分之后的输入。这就是样式化组件如何传递你的道具来在你的组件中做一些特殊的事情。

styled.button并且styled.button.attrs()都返回一个以这种方式使用标记的模板文字调用的函数。如果他们返回一个可渲染的 React 组件,那么您将根本无法提供 css。

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

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


推荐阅读