reactjs 已发布的样式化组件react库无法访问用户应用程序ThemeProvider

f3temu5u  于 2023-04-11  发布在  React
关注(0)|答案(3)|浏览(168)

所以我正在为这家公司构建一个设计系统,组件系统在设计系统故事书中正确显示。

TypeError: Cannot read property 'width' of undefined in theme.border.width

设计系统项目:

/// src/components/Button/index.js
import { Wrapper } from './styles'
import React from 'react'

export const Button = (props) => (
  <Wrapper {...props}>
    {children}
  </Wrapper>
)

.

///src/components/Button/styles.js    
export const Wrapper = styled.button`
...
border-width: ${({theme}) => theme.border.width};
...
`

.

/// .storybook/preview.js
import React from 'react'
import { ThemeProvider } from 'styled-components'
import { GlobalStyle } from '../src/styles/globalStyles'
import { theme } from '../src/styles/theme'

export const parameters = {
  actions: { argTypesRegex: '^on[A-Z].*' }
}
export const decorators = [
  Story => (
      <ThemeProvider theme={theme}>
        <GlobalStyle />
        <Story />
      </ThemeProvider>
    )
 ]

.

/// src/index.js
...
export { Button } from 'components/Button'
export { theme } from 'style/theme'

...

.

/// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/env',
      {
        modules: false
      }
    ],
    ['@babel/preset-react']
  ],
  plugins: [
    [
      'styled-components',
      {
        ssr: true,
        displayName: true,
        preprocess: false,
        minify: false
      }
    ]
  ]
}

.

///rollup.config.js
import babel from 'rollup-plugin-babel'
import includePaths from 'rollup-plugin-includepaths'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'

export default [
  {
    input: 'src/index.js',
    output: [
      {
        name: 'rollup-tutorial',
        file: 'dist/index.js',
        format: 'es'
      }
    ],
    plugins: [
      babel({
        exclude: 'node_modules/**'
      }),
      includePaths({
        paths: ['src'],
        extensions: ['.js', '.json', '.html']
      }),
      peerDepsExternal()
    ]
  }
]

.

/// package.json
{
  "name": "design-system",
  "main": "dist/index.js"
  "files: ["dist"],
  "scripts": {
    ...
    "build": "rollup --config"
    ...
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/preset-react": "^7.12.10",
    "@babel/preset-env": "^7.12.13",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "rollup": "^2.38.4",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-includepaths": "^0.2.4",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "styled-components": "^5.2.1",
  },
 "peerDependencies": {
    "prop-types": ">= 15.x.x",
    "react": ">= 17.x.x",
    "styled-components": ">= 5.x.x",
  }
}

App消费端NextJs默认配置

/// .babelrc

{
  "presets": ["next/babel"],
  "env": {
    "development": {
      "plugins": [
        [
          "styled-components",
          {
            "ssr": true,
            "displayName": true
          }
        ]
      ]
    },
    "production": {
      "presets": [
        "next/babel"
      ],
      "plugins": [
        [
          "styled-components",
          {
            "ssr": true,
            "displayName": false
          }
        ]
      ]
    }
  }
}

.

///package.json
{
  ...
  "dependencies":  {
    ...
    "design-system": "../design-system/",
    ...
  }
  ...
}

.

/// pages/_app.js
import { ThemeProvider } from 'styled-components'
import { theme } from 'design-system'

function MyApp({ Component, pageProps }) {
  console.log(theme)
  return (
    <ThemeProvider theme={theme}>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

.

///pages/index.js
import { Button } 'design-system'

export default function Home() {
  return (
   <Button />
  )
}

注意:

console.log(theme)打印预期的主题,但是按钮无法访问样式化组件提供的主题。我想我错过了一些重要的babel rollup配置或其他东西

注2:

我已经尝试过用withComponentHOC Package 组件,唯一可行的解决方案是下一段代码

///pages/index.js
import { Button } 'design-system'
import { useTheme } 'styled-components'

export default function Home() {
  const theme = useTheme()
  return (
   <Button theme={theme} />
  )
}

但这就失去了使用上下文的全部意义
先谢谢你了

zzwlnbp8

zzwlnbp81#

我在使用storybook和emotion/styled-components开发组件库时遇到过类似的问题。问题是我在消费者应用程序中使用了styled-components的ThemeProvider,就像你在_app.js中所做的那样。解决方案是在组件库上创建并导出一个自定义的ThemeProvider,使用库的styled-component包,如下所示:

import { ThemeProvider } from 'styled-components'
import { theme as defaultTheme } from '../src/styles/theme'

const CustomThemeProvider = ({ theme = defaultTheme, children }) => (
  <ThemeProvider theme={theme}>
    {children}
  </ThemeProvider>
)

export { CustomThemeProvider }

然后在消费者应用中使用

/// pages/_app.js
import { CustomThemeProvider, theme } from 'design-system'

function MyApp({ Component, pageProps }) {
  console.log(theme)
  return (
    <CustomThemeProvider theme={theme}>
      <Component {...pageProps} />
    </CustomThemeProvider>
  )
}
hujrc8aj

hujrc8aj2#

样式化组件FAQ建议不要将样式化组件与捆绑包沿着发布。这为我解决了上述问题。
https://styled-components.com/docs/faqs#i-am-a-library-author-should-i-bundle-styledcomponents-with-my-library

sc4hvdpw

sc4hvdpw3#

你能试试这个吗?我的情况和你一样。
您应该从自定义应用程序导入ThemeProvider
就像这样

// pages/_app.js
// do this 
import { ThemeProvider , theme } from 'design-system';

// not like this
import { ThemeProvider } from 'styled-components';
import { theme } from 'design-system';

function MyApp({ Component, pageProps }) {
  console.log(theme);
  return (
    <ThemeProvider theme={theme}>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

相关问题