已发布的样式组件反应库无权访问用户应用程序 ThemeProvider
Published styled-components react library does not have access to user app ThemeProvider
所以我正在为这家公司构建一个设计系统,组件系统在设计系统故事书中正确显示。但是当我在消费者应用程序中导入它时,出现以下错误
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",
}
}
应用消费者 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:
我已经尝试在 withComponent HOC 中包装组件
唯一可行的解决方案是下一段代码
///pages/index.js
import { Button } 'design-system'
import { useTheme } 'styled-components'
export default function Home() {
const theme = useTheme()
return (
<Button theme={theme} />
)
}
但这失去了使用上下文的全部意义
提前致谢
我在使用故事书和 emotion/styled-components 开发组件库时遇到了类似的问题。问题是我正在使用来自消费者应用程序的样式化组件的 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>
)
}
styled-components FAQ 建议不要将 styled-components 与 bundle 一起运送。这为我解决了上述问题。
所以我正在为这家公司构建一个设计系统,组件系统在设计系统故事书中正确显示。但是当我在消费者应用程序中导入它时,出现以下错误
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",
}
}
应用消费者 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:
我已经尝试在 withComponent HOC 中包装组件 唯一可行的解决方案是下一段代码
///pages/index.js
import { Button } 'design-system'
import { useTheme } 'styled-components'
export default function Home() {
const theme = useTheme()
return (
<Button theme={theme} />
)
}
但这失去了使用上下文的全部意义
提前致谢
我在使用故事书和 emotion/styled-components 开发组件库时遇到了类似的问题。问题是我正在使用来自消费者应用程序的样式化组件的 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>
)
}
styled-components FAQ 建议不要将 styled-components 与 bundle 一起运送。这为我解决了上述问题。