【问题标题】:How to extend or merge Styled Components theme如何扩展或合并样式化组件主题
【发布时间】:2019-04-02 22:29:59
【问题描述】:

我有一个基于样式化组件的组件库,它有自己的一组主题设置,在大多数情况下,这些设置永远不需要被覆盖。我正在将此组件库拉入另一个项目,该项目也使用样式组件并拥有自己的主题。我如何从组件库和这个项目中导入组件,并确保它们中的每一个都只提供来自其相应 repo 的主题值?我不想覆盖我的组件库主题,我想管理 2 个单独的主题,以便我的组件库可以访问默认主题,并且这个其他项目可以为其自己的组件定义一个单独的主题对象

示例: 独立项目

const theme = {
  colors: {
    error: '#f23f3f',
  }
}

import { SeparateProjectThemeProvider } from 'separate-proj';

class App extends React.Component {
 render () {
  return (
   <SeparateProjectThemeProvider theme={theme}>
     <h1>Hello</h1>
   </SeparateProjectThemeProvider>
  )
 }
}

组件库

const theme = {
  colors: {
    brand: '#3bbdca',
  }
}

import { ThemeProvider } from "styled-components";

import defaultTheme from "./theme-settings";

const mergeThemes = (theme1, theme2) => {
  const mergedTheme = { ...theme1, ...theme2 };
  return mergedTheme;
};

const CustomThemeProvider = props => {
  const customTheme = {
    custom: Object.assign({}, defaultTheme)
  };

  return (
    <ThemeProvider theme={mergeThemes(customTheme, props.theme)}>
        {props.children}
    </ThemeProvider>
  );
};

export default CustomThemeProvider;

【问题讨论】:

  • 您的组件库中大约有多少个组件?
  • 如果两个主题定义相同的属性(例如,一个将错误颜色定义为红色,另一个将其定义为栗色)您希望它们使用各自的值还是希望其中一个赢得其他的?
  • 我有大约 20 个组件。理想情况下,我希望他们保持各自的价值观
  • 您的组件库中的任何组件是否都嵌套了项目中的组件?您是否经常遇到以下情况: 如果您的组件库有“选项卡”或“面板”组件,然后您将主项目中的子组件放置在其中。
  • 我没有看到这种情况发生,但这是可能的。到目前为止,组件库是一个小而简单的库,在大多数情况下用于在我们公司的产品中构建更大的组件

标签: javascript css reactjs styled-components


【解决方案1】:

下面的代码将演示几个选项 - 使用适当的主题提供程序 (WrappedTitle) 预先包装每个 component-lib 组件,或者在使用时包装它们(“Hello Component World!”部分)。

// Sample component-lib/index.js
import React from 'react';
import styled from "styled-components";
import {ThemeProvider} from "styled-components";

const theme = {
  titleColor: "green"
};
export const CompLibThemeProvider = props => {
  const customTheme = Object.assign({}, theme, props.theme);
  return (
    <ThemeProvider theme={customTheme}>
        {props.children}
    </ThemeProvider>
  );
};

export const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: ${props => props.theme.titleColor};
`;
export const WrappedTitle = (props) => {
  return (<CompLibThemeProvider><Title {...props}/></CompLibThemeProvider>);
};

这里是一些示例项目代码:

// App.js
import React from 'react';
import styled from 'styled-components';
import {Title, CompLibThemeProvider, WrappedTitle} from 'component-lib';
import {ThemeProvider} from "styled-components";

const theme = {
  titleColor: "red"
};

export const BigTitle = styled.h1`
  font-size: 5em;
  text-align: center;
  color: ${props => props.theme.titleColor};
`;

const ProjectThemeProvider = props => {

  return (
    <ThemeProvider theme={Object.assign({}, theme, props.theme)}>
        {props.children}
    </ThemeProvider>
  );
};
const App = () => {
  return (
    <>
    <ProjectThemeProvider>
      <>
        <BigTitle>Hello Big World!</BigTitle>
        <WrappedTitle>Hello Pre-wrapped World!</WrappedTitle>
      </>
    </ProjectThemeProvider>
    <CompLibThemeProvider><Title>Hello Component World!</Title></CompLibThemeProvider>
    </>
  );
}

export default App;

【讨论】:

  • 感谢我在解决我遇到的其他一些问题后立即实施。
猜你喜欢
  • 2020-10-09
  • 2019-03-28
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 2019-03-25
相关资源
最近更新 更多