question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to use isomorphic-style-loader effectively with component libraries?

See original GitHub issue

I’m trying to use React Toolbox alongside isomorphic-style-loader in my project. React-Toolbox uses CSS modules for its components.

My current solution that I haven’t implemented yet is to import each component and its styles, apply withStyles, and export the new component. An example file would look like:

// component_library/Button/index.js
import Button from 'react-toolbox/lib/button';
import buttonStyles from 'react-toolbox/lib/button/theme.scss';
import withStyles from 'isomorphic-style-loader/lib/withStyles';

export default withStyles(buttonStyles)(Button);

Is there a way to apply isomorphic-style-loader’s withStyles() across all of a library’s components without me having to manually import each file and re-export it?

<bountysource-plugin> --- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/38158821-how-to-use-isomorphic-style-loader-effectively-with-component-libraries?utm_campaign=plugin&utm_content=tracker%2F26439769&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F26439769&utm_medium=issues&utm_source=github). </bountysource-plugin>

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:2
  • Comments:18 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
jusschcommented, Oct 25, 2016

Interesting, what do you do with MyComponent.css though? Are you saying to use it like so:

/* ./Button/index.js */
import Button from 'react-toolbox/lib/button';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import buttonStyles from './overwrite.css';

export default withStyles(buttonStyles)(Button);
/* ./Button/overwrite.css */
@import 'react-toolbox/lib/button/theme.css';

.someSelectorToOverwrite {
  color: red;
}

If so, I don’t believe that works. The original button component at react-toolbox/lib/button is still referencing the old react-toolbox/lib/button/theme.css, which means that the Button would use the wrong localized class names.

3reactions
webicancommented, Nov 21, 2016

There you go, fresh out out of the oven. Use it instead of withStyles. It expects the same arguments as themr() function from react-css-themr, except it has isomorphic-style-loader superpowers 😃

Theming react-toolbox components is very easy with react-css-themr. Read react-toolbox installation guide to see how to set it up with themr. Besides themr is very nice to use for styling your own components as well. You can even switch themes at runtime with ThemeProvider. (Although there is a bug (https://github.com/javivelasco/react-css-themr/issues/34), which can be fixed to make componentWillReceiveProps() method of themr() function track also changes to the context. I’m too lazy to do it myself, personally I don’t need runtime theme switching right now.

The code hasn’t been tested properly so please be gentle. Let me know if you spot any bugs.

import React, { Component, PropTypes } from 'react';
import hoistStatics from 'hoist-non-react-statics';
import { themr } from 'react-css-themr';

const CONTEXT_THEME = 'CONTEXT_THEME';
const PROPS_THEME = 'PROPS_THEME';
const DEFAULT_THEME = 'DEFAULT_THEME';

export default (componentName, defaultTheme, options) => (ComposedComponent) => {
  const ThemrComponent = themr(
    componentName, defaultTheme, options
  )(ComposedComponent);

  const displayName = ComposedComponent.displayName
                   || ComposedComponent.name
                   || 'Component';

  class WithThemr extends Component {
    static displayName = `WithThemr(${displayName})`;

    static contextTypes = {
      themr: PropTypes.object,
      insertCss: PropTypes.func,
    }

    static propTypes = {
      ...ThemrComponent.propTypes,
    }

    static defaultProps = {
      ...ThemrComponent.defaultProps,
    }

    constructor(props) {
      super(props);
      this.removeThemes = {};
    }

    componentWillMount() {
      if (this.props.composeTheme) {
        // composeTheme option is not false, meaning styles of the component
        // are composed of Context, Default and Props themes.

        const contextTheme = this.context.themr.theme[componentName];
        this.insertTheme(CONTEXT_THEME, contextTheme);
        this.insertTheme(DEFAULT_THEME, defaultTheme);
      }

      // Props theme has the highest priority of the three and needs to be
      // inserted regardless of the composeTheme option.
      this.insertTheme(PROPS_THEME, this.props.theme);
    }

    componentWillReceiveProps(nextProps, nextContext) {
      const contextTheme = this.context.themr.theme[componentName];
      const nextContextTheme = nextContext.themr.theme[componentName];

      if (nextProps.composeTheme) {
        // composeTheme option is not false, meaning styles of the component
        // are composed of Context, Default and Props themes.

        if (!this.props.composeTheme) {
          // composeTheme option used to be false, insert Context and Default
          // themes.
          this.insertTheme(CONTEXT_THEME, nextContextTheme);
          this.insertTheme(DEFAULT_THEME, defaultTheme);
        } else if (nextContextTheme !== contextTheme) {
          // Context theme has changed, replace it.
          this.removeTheme(CONTEXT_THEME);
          this.insertTheme(CONTEXT_THEME, nextContextTheme);
        }

        if (nextProps.theme !== this.props.theme) {
          // Props theme has changed, replace it.
          this.removeTheme(PROPS_THEME);
          this.insertTheme(PROPS_THEME, nextProps.theme);
        }
      } else {
        // composeTheme option is false, meaning styles of the component
        // are not composed and are provided by a theme with the highest priority.

        if (nextProps.theme || defaultTheme) {
          // Props theme and Default theme have higher priority than Context
          // theme. When either of them exist, we need to remove Context theme.
          this.removeTheme(CONTEXT_THEME);
        }

        if (nextProps.theme) {
          // Props theme has a higher priority than Default theme.
          // When it exists, we need to remove Default theme.
          this.removeTheme(DEFAULT_THEME);
        }
      }
    }

    componentWillUnmount() {
      this.removeTheme(CONTEXT_THEME);
      this.removeTheme(DEFAULT_THEME);
      this.removeTheme(PROPS_THEME);
    }

    insertTheme(type, theme) {
      if (theme) {
        this.removeThemes[type] = this.context.insertCss.apply(
          undefined, [theme]
        );
      }
    }

    removeTheme(type) {
      if (this.removeThemes[type]) {
        setTimeout(this.removeThemes[type], 0);
      }
    }

    render() {
      return <ThemrComponent {...this.props} />;
    }
  }

  WithThemr.ComposedComponent = ThemrComponent;

  return hoistStatics(WithThemr, ComposedComponent);
};

Read more comments on GitHub >

github_iconTop Results From Across the Web

How can I publish react components on npm based on ...
I want to move my shared components to npm so I can use them in my projects easily. I use the isomorphic-style-loader to...
Read more >
@async3619/isomorphic-style-loader - npm
CSS style loader for Webpack optimized for critical path CSS rendering and isomoprhic web apps. Latest version: 5.1.1, last published: 3 ...
Read more >
The Pain and the Joy of creating isomorphic apps in ReactJS
The only thing we should do is to take React Js library and use it ... We use webpack and usually we import...
Read more >
isomorphic-style-loader examples - CodeSandbox
Learn how to use isomorphic-style-loader by viewing and forking example apps that make use of isomorphic-style-loader on CodeSandbox. ; parityapp/admin-panel.
Read more >
Render CSS on Server Side with React and Isomorphic-Style ...
1. Install the loader · 2. Make sure to use it on both server and browser Webpack configs. · 3. Use it in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found