Как настроить приложение create-response-app для экспорта CSS в два разных файла

Я работаю над проектом, который позволит пользователю динамически изменять темы и использует под капотом reactstrap и styled-components. Мы хотим настроить все переменные через SASS, который работает нормально. Чтобы сделать эти переменные доступными для стилизованных компонентов, мы использовали sass-extract-loader для создания объектов темы.

Все это отлично работает, когда мы статически выбираем одну из тем, но мне не удалось заставить ее работать динамически и надежно. У меня две проблемы:

1) В процессе разработки прекрасно работает переключение темы один раз. Если я изменю его снова, мои нестилевые компоненты (то есть необработанные компоненты reactstrap) будут стилизованы со второй темой. Я считаю, что это потому, что вторая тема загружает и переопределяет исходный CSS. 2) В производстве я получаю то же сочетание, что и # 1 по умолчанию (то есть, поскольку все файлы CSS объединяются в один пакет, компоненты reactstrap имеют один стиль, а стилизованные компоненты "уважают" тему) .

Я считаю, что лучший вариант для нас - иметь темы в двух отдельных файлах CSS и переключать "альтернативные" ссылки на них. Я просто не знаю, как настроить CRA, чтобы не помещать весь CSS в один основной пакет, и позволить мне вручную добавлять ссылки на альтернативные таблицы стилей. Если я могу разделить их на отдельные файлы, я считаю, что смогу просто добавить теги и динамически поменять местами свойство rel = "alternate".

Возможно, есть более эффективные способы добиться этого. Насколько я понимаю, самый простой способ управлять темами Bootstrap - это через переменные SASS, и я хотел бы убедиться, что эти переменные не нужно переопределять при использовании их в стилизованных компонентах.


person rfestag    schedule 09.11.2018    source источник


Ответы (1)


Если вы хотите применить стили условно, вы можете импортировать свои таблицы стилей в файл 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) переменной. Затем эту переменную можно использовать для использования компонента Provider или Consumer внутри ваших компонентов React.

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>;
  }
}
person Donny Verduijn    schedule 10.11.2018