如何配置create-react-app将CSS导出到两个不同的文件中

时间:2018-11-09 23:49:50

标签: sass create-react-app styled-components reactstrap

我正在研究一个项目,该项目将动态允许用户更改主题,并在后台使用reactstrap和样式化组件。我们想通过SASS配置所有变量,效果很好。为了使这些变量可用于样式组件,我们一直在使用sass-extract-loader创建主题对象。

当我们静态选择一个主题时,所有这些都很好用,但我无法使其可靠地动态工作。我有两个问题:

1)在开发中,一次切换主题 效果很好。如果我再次更改它,则我的非样式化组件(即原始reactstrap组件)将使用第二个主题进行样式设置。我相信这是因为第二个主题是加载和覆盖原始CSS。 2)在生产中,默认情况下,我得到的混合效果与#1相同(即,因为所有CSS文件都被放到一个单独的包中,因此reactstrap组件以一种方式设置样式,而有样式的组件则“赞扬”主题)

我认为对我们来说最好的选择是将主题放在两个单独的CSS文件中,并在它们之间切换“替代”关联。我只是不知道如何配置CRA而不是将所有CSS都放在一个主包中,而是让我手动添加指向替代样式表的链接。如果我可以将它们拆分成单独的文件,我相信我可以添加标签并动态交换rel =“ alternate”属性。

可能会有更好的方法来完成此任务。我的理解是控制Bootstrap主题的最简单方法是通过SASS变量,并且我想确保在样式组件中使用它们时不必重新定义这些变量。

1 个答案:

答案 0 :(得分:0)

如果要有条件地应用样式,则可以将样式表导入index.js文件,并通过上下文API将其提供给所有组件。首先,我们将CSS文件导入index.js

import themeA from './css/themeA.css';
import themeB from './css/themeB.css';

但是,通过这种方式使用, 您不能在两个CSS文件中都有元素选择器 ,因为它们将从两个文件中全局应用。但是,您可以导入一个补充所选主题的额外样式表,在其中定义元素选择器。

通过使用CSS模块,您无需元素选择器。如果您不熟悉CSS模块,则可能需要阅读本文:https://javascriptplayground.com/css-modules-webpack-react/

如果仍然需要在一个主题中应用元素选择器,可以这样做,但是它们也会以这种方式应用于您的另一主题中。

 import './css/default.css';

下面的示例是React文档的修改版本:https://reactjs.org/docs/context.html

  

在此示例中,我们绘制了一个按钮,当   它的点击。此示例中的三个部分至关重要   了解您是否要使用React的上下文API。

1。创建上下文。 通过将React.createContext(yourValue)的返回值分配给变量来完成创建上下文。然后可以使用此变量在React组件中使用Provider或Consumer组件。

const ThemeContext = React.createContext();

2。通过将其作为道具传递给您的Provider组件来提供值。现在,您的所有组件都可以访问该值。

class App extends React.Component {
  swapTheme() {
    this.setState({ withThemeA: !this.state.withThemeA });
  }
  render() {
    const theme = this.state.withThemeA ? themeA : themeB;
    return (
      <ThemeContext.Provider value={theme}>
        <ThemedButton onClick={this.swapTheme} />
      </ThemeContext.Provider>
    );
  }
}

3。收听使用Consumer组件的更新。 要监听更改,您需要使用Consumer组件。传递的函数接收主题作为参数,因此可以将其分配给按钮元素的className属性。

class ThemedButton extends React.Component {
  render() {
    return <ThemeContext.Consumer>
      {theme => <button className={theme.Button}}>click me</button>}
    </ThemeContext.Consumer>;
  }
}