已发布的样式组件反应库无权访问用户应用程序 ThemeProvider

Posted

技术标签:

【中文标题】已发布的样式组件反应库无权访问用户应用程序 ThemeProvider【英文标题】:Published styled-components react library does not have access to user app ThemeProvider 【发布时间】:2021-05-07 20:01:49 【问题描述】:

所以我正在为这家公司构建一个设计系统,并且组件系统在设计系统故事书中正确显示。但是当我在消费者应用程序中导入它时,我收到以下错误

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',
      
        s-s-r: 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",
          
            "s-s-r": true,
            "displayName": true
          
        ]
      ]
    ,
    "production": 
      "presets": [
        "next/babel"
      ],
      "plugins": [
        [
          "styled-components",
          
            "s-s-r": 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:

我已经尝试将组件包装在 withComponent HOC 中 唯一可行的解​​决方案是下一段代码

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

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

但这失去了使用上下文的全部意义

提前致谢

【问题讨论】:

【参考方案1】:

在使用故事书和情感/样式组件开发组件库时,我遇到了类似的问题。问题是我正在使用来自消费者应用程序的样式化组件的 ThemeProvider,就像您在 _app.js 中所做的那样。解决方案是使用库的 styled-component 包在组件库上创建和导出自定义 ThemeProvider,如下所示:

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>
  )

【讨论】:

【参考方案2】:

样式组件常见问题解答建议不要将样式组件与捆绑包一起提供。这为我解决了上述问题。

https://styled-components.com/docs/faqs#i-am-a-library-author-should-i-bundle-styledcomponents-with-my-library

【讨论】:

以上是关于已发布的样式组件反应库无权访问用户应用程序 ThemeProvider的主要内容,如果未能解决你的问题,请参考以下文章

gcloud:用户无权访问服务帐户“默认”

将 Blazor 组件渲染到现有 div(Blazor 无权访问)

svn访问版本库时一直提示:please wait while the repository browser is initializing,没有其他反应

无权访问 GIT 存储库。我该如何进行?

用户无权访问此对象。带储藏火库

WebPack 为导入的样式表的类添加下划线,从而破坏反应组件的样式