Use CSS-in-JavaScript with themes for React without being tightly coupled to one implementation

  • By Airbnb
  • Last update: Nov 11, 2022
  • Comments: 16

react-with-styles Version Badge

dependency status dev dependency status License Downloads

npm badge

Use CSS-in-JavaScript for your React components without being tightly coupled to one implementation (e.g. Aphrodite, Radium, or React Native). Easily access shared theme information (e.g. colors, fonts) when defining your styles.

Interfaces

Other resources

How to use

Step 1. Define your theme

Create a module that exports an object with shared theme information like colors.

export default {
  color: {
    primary: '#FF5A5F',
    secondary: '#00A699',
  },
};

Step 2. Choose an interface

You will need to choose the react-with-styles interface that corresponds to the underlying CSS-in-JS framework that you use in your app. Look through the list of existing interfaces, or write your own!

If you choose to write your own, the interface must implement the following functions:

Function Description
create Function that outputs the styles object injected through props.
(Optional, but required if createLTR is not provided).
createLTR LTR version of create.
(Required, unless a create function is provided)
createRTL RTL version of create.
(Required, unless a create function is provided)
resolve This is the css function that is injected through props. It outputs the attributes used to style an HTML element.
(Optional, but required if no resolveLTR is provided)
resolveLTR LTR version of resolve.
(Required, unless the resolve function is provided)
resolveRTL RTL version of resolve.
(Required, unless the resolve function is provided)
flush? Flush buffered styles before rendering. This can mean anything you need to happen before rendering.
(Optional)

Step 3. Register the chosen theme and interface

Option 1: Using React Context (recommended)

☝️ Requires React 16.6+

As of version 4.0.0, registering the theme and interface can be accomplished through React context, and is the recommended way of registering the theme, interface, and direction.

For example, if your theme is exported by MyTheme.js, and you want to use Aphrodite through the react-with-styles-interface-aphrodite insterface, wrap your application with the WithStylesContext.Provider to provide withStyles with that interface and theme:

import React from 'react';
import WithStylesContext from 'react-with-styles/lib/WithStylesContext';
import AphroditeInterface from 'react-with-styles-interface-aphrodite';
import MyTheme from './MyTheme';

export default function Bootstrap({ direction }) {
  return (
    <WithStylesContext.Provider
      value={{
        stylesInterface: AphroditeInterface,
        stylesTheme: MyTheme,
        direction,
      }}
    >
      <App />
    </WithStylesContext.Provider>
  );
}

To support people using a right-to-left (RTL) context, we recommend using react-with-styles along with react-with-direction. You can provide the direction directly if you have a utility that determines it like in the example above, or you can use the provided utility, WithStylesDirectionAdapter, to grab the direction that's already been set on the react-with-direction context and amend WithStylesContext with it.

import React from 'react';
import WithStylesContext from 'react-with-styles/lib/WithStylesContext';
import WithStylesDirectionAdapter from 'react-with-styles/lib/providers/WithStylesDirectionAdapter';
import AphroditeInterface from 'react-with-styles-interface-aphrodite';
import MyTheme from './MyTheme';

export default function Bootstrap() {
  return (
    <WithStylesContext.Provider
      value={{
        stylesInterface: AphroditeInterface,
        stylesTheme: MyTheme,
      }}
    >
      <WithStylesDirectionAdapter>
        <App />
      </WithStylesDirectionAdapter>
    </WithStylesContext.Provider>
  );
}

Or simply wrap the Bootstrap function above in withDirection yourself.

☝️ Note on performance: Changing the theme many times will cause components to recalculate their styles. Avoid recalculating styles by providing one theme at the highest possible level of your app.

Option 2: Using the ThemedStyleSheet (legacy)

The legacy singleton-based API (using ThemedStyleSheet) is still supported, so you can still use it to register the theme and interface. You do not have to do this if you use the WithStylesContext.Provider. Keep in mind that this API will be deprecated in the next major version of react-with-styles. You can set this up in your own withStyles.js file, like so:

import ThemedStyleSheet from 'react-with-styles/lib/ThemedStyleSheet';
import AphroditeInterface from 'react-with-styles-interface-aphrodite';
import { withStyles } from 'react-with-styles';

import MyTheme from './MyTheme';

ThemedStyleSheet.registerTheme(MyTheme);
ThemedStyleSheet.registerInterface(AphroditeInterface);

export { withStyles, ThemedStyleSheet };

It is convenient to pass through withStyles from react-with-styles here so that everywhere you use them you can be assured that the theme and interface have been registered. You could likely also set this up as an initializer that is added to the top of your bundles and then use react-with-styles directly in your components.

Because the ThemedStyleSheet implementation stores the theme and interface in variables outside of the React tree, we do not recommended it. This approach does not parallelize, especially if your build systems or apps require rendering with multiple themes.

Step 4. Styling your components

In your components, use withStyles() to define styles. This HOC will inject the right props to consume them through the CSS-in-JS implementation you chose.

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles, withStylesPropTypes } from './withStyles';

const propTypes = {
  ...withStylesPropTypes,
};

function MyComponent({ styles, css }) {
  return (
    <div>
      <a
        href="/somewhere"
        {...css(styles.firstLink)}
      >
        A link to somewhere
      </a>

      {' '}
      and
      {' '}

      <a
        href="/somewhere-else"
        {...css(styles.secondLink)}
      >
        a link to somewhere else
      </a>
    </div>
  );
}

MyComponent.propTypes = propTypes;

export default withStyles(({ color }) => ({
  firstLink: {
    color: color.primary,
  },

  secondLink: {
    color: color.secondary,
  },
}))(MyComponent);

You can also use the useStyles hook or a decorator.


Documentation

withStyles([ stylesThunk [, options ] ])

This is a higher-order function that returns a higher-order component used to wrap React components to add styles using the theme. We use this to make themed styles easier to work with.

stylesThunk will receive the theme as an argument, and it should return an object containing the styles for the component.

The wrapped component will receive the following props:

  1. styles - Object containing the processed styles for this component. It corresponds to evaluating stylesInterface.create(stylesThunk(theme)) (or their directional counterparts).
  2. css - Function to produce props to set the styles with on an element. It corresponds to stylesInterface.resolve (or their directional counterparts).
  3. theme - This is the theme object that was registered. You can use it during render as needed, say for inline styles.

Example usage

You can use withStyles() as an HOC:

import React from 'react';
import { withStyles } from './withStyles';

function MyComponent({ css, styles }) {
  return (
    <div {...css(styles.container)}>
      Try to be a rainbow in someone's cloud.
    </div>
  );
}

export default withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },
}))(MyComponent);

As a decorator:

import React from 'react';
import { withStyles } from './withStyles';

@withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },
}))
export default function MyComponent({ styles, css }) {
  return (
    <div {...css(styles.container)}>
      Try to be a rainbow in someone's cloud.
    </div>
  );
}

You can also use the experimental hook:

import React from 'react';
import useStyles from 'react-with-styles/lib/hooks/useStyles';

function stylesFn({ color, unit }) {
  return ({
    container: {
      color: color.primary,
      marginBottom: 2 * unit,
    },
  });
}

export default function MyComponent() {
  const { css, styles } = useStyles({ stylesFn });
  return (
    <div {...css(styles.container)}>
      Try to be a rainbow in someone's cloud.
    </div>
  );
}

Options

pureComponent (default: false)

By default withStyles() will create a functional component. If you want to apply the rendering optimizations offered by React.memo, you can set the pureComponent option to true to create a pure functional component instead.

If using the withStyles utility that is found in lib/deprecated/withStyles, it will instead use a React.PureComponent rather than a React.Component. Note that this has a React version requirement of 15.3.0+.

stylesPropName (default: 'styles')

By default, withStyles() will pass down the styles to the wrapped component in the styles prop, but the name of this prop can be customized by setting the stylesPropName option. This is useful if you already have a prop called styles and aren't able to change it.

import React from 'react';
import { withStyles, withStylesPropTypes } from './withStyles';

function MyComponent({ withStylesStyles, css }) {
  return (
    <div {...css(withStylesStyles.container)}>
      Try to be a rainbow in someone's cloud.
    </div>
  );
}

MyComponent.propTypes = {
  ...withStylesPropTypes,
};

export default withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },
}), { stylesPropName: 'withStylesStyles' })(MyComponent);
cssPropName (default 'css')

The css prop name can also be customized by setting the cssPropName option.

import React from 'react';
import { withStyles, withStylesPropTypes } from './withStyles';

function MyComponent({ withStylesCss, styles }) {
  return (
    <div {...withStylesCss(styles.container)}>
      Try to be a rainbow in someone's cloud.
    </div>
  );
}

MyComponent.propTypes = {
  ...withStylesPropTypes,
};

export default withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },
}), { cssPropName: 'withStylesCss' })(MyComponent);
themePropName (default 'theme')

The theme prop name can also be customized by setting the themePropName option.

import React from 'react';
import { withStyles, withStylesPropTypes } from './withStyles';

function MyComponent({ css, styles, withStylesTheme }) {
  return (
    <div {...css(styles.container)}>
      <Background color={withStylesTheme.color.primary}>
        Try to be a rainbow in someone's cloud.
      </Background>
    </div>
  );
}

MyComponent.propTypes = {
  ...withStylesPropTypes,
};

export default withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },
}), { themePropName: 'withStylesTheme' })(MyComponent);
flushBefore (default: false)

Some components depend on previous styles to be ready in the component tree when mounting (e.g. dimension calculations). Some interfaces add styles to the page asynchronously, which is an obstacle for this. So, we provide the option of flushing the buffered styles before the rendering cycle begins. It is up to the interface to define what this means.

css(...styles)

This function takes styles that were processed by withStyles(), plain objects, or arrays of these things. It returns an object with attributes that must be spread into a JSX element. We recommend not inspecting the results and spreading them directly onto the element. In other words className and style props must not be used on the same elements as css().

import React from 'react';
import { withStyles, withStylesPropTypes } from './withStyles';

const propTypes = {
  ...withStylesPropTypes,
};

function MyComponent({ css, styles, bold, padding, }) {
  return (
    <div {...css(styles.container, { padding })}>
      Try to be a rainbow in{' '}
      <a
        href="/somewhere"
        {...css(styles.link, bold && styles.link_bold)}
      >
        someone's cloud
      </a>
    </div>
  );
}

MyComponent.propTypes = propTypes;

export default withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },

  link: {
    color: color.secondary,
  },

  link_bold: {
    fontWeight: 700,
  },
}))(MyComponent);

Accessing your wrapped component with a ref

React 16.3 introduced the ability to pass along refs with the React.forwardRef helper, allowing you to write code like this.

const MyComponent = React.forwardRef(
  function MyComponent({ css, styles }, forwardedRef) {
    return (
      <div {...css(styles.container)} ref={forwardedRef}>
        Hello, World
      </div>
    );
  }
);

Refs will not get passed through HOCs by default because ref is not a prop. If you add a ref to an HOC, the ref will refer to the outermost container component, which is usually not desired. withStyles is set up to pass along your ref to the wrapped component.

const MyComponentWithStyles = withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },
}))(MyComponent);

// the ref will be passed down to MyComponent, which is then attached to the div
const ref = React.createRef()
<MyComponentWithStyles ref={ref} />

ThemedStyleSheet (legacy)

Registers themes and interfaces.

⚠️ Deprecation Warning: ThemedStyleSheet is going to be deprecated in the next major version. Please migrate your applications to use WithStylesContext to provide the theme and interface to use along with withStyles or useStyles. In the meantime, you should be able to use both inside your app for a smooth migration. If this is not the case, please file an issue so we can help.

ThemedStyleSheet.registerTheme(theme) (legacy)

Registers the theme. theme is an object with properties that you want to be made available when styling your components.

import ThemedStyleSheet from 'react-with-styles/lib/ThemedStyleSheet';

ThemedStyleSheet.registerTheme({
  color: {
    primary: '#FF5A5F',
    secondary: '#00A699',
  },
});

ThemedStyleSheet.registerInterface(interface) (legacy)

Instructs react-with-styles how to process your styles.

import ThemedStyleSheet from 'react-with-styles/lib/ThemedStyleSheet';
import AphroditeInterface from 'react-with-styles-interface-aphrodite';

ThemedStyleSheet.registerInterface(AphroditeInterface);

Other Examples

With React Router's Link

React Router's <Link/> and <IndexLink/> components accept activeClassName='...' and activeStyle={{...}} as props. As previously stated, css(...styles) must spread to JSX, so simply passing styles.thing or even css(styles.thing) directly will not work. In order to mimic activeClassName/activeStyles you can use React Router's withRouter() Higher Order Component to pass router as prop to your component and toggle styles based on router.isActive(pathOrLoc, indexOnly). This works because <Link /> passes down the generated className from css(..styles) down through to the final leaf.

import React from 'react';
import { withRouter, Link } from 'react-router';
import { css, withStyles } from '../withStyles';

function Nav({ router, styles }) {
  return (
    <div {...css(styles.container)}>
      <Link
        to="/"
        {...css(styles.link, router.isActive('/', true) && styles.link_bold)}
      >
        home
      </Link>
      <Link
        to="/somewhere"
        {...css(styles.link, router.isActive('/somewhere', true) && styles.link_bold)}
      >
        somewhere
      </Link>
    </div>
  );
}

export default withRouter(withStyles(({ color, unit }) => ({
  container: {
    color: color.primary,
    marginBottom: 2 * unit,
  },

  link: {
    color: color.primary,
  },

  link_bold: {
    fontWeight: 700,
  }
}))(Nav));

In the wild

Organizations and projects using react-with-styles.

Github

https://github.com/airbnb/react-with-styles

Comments(16)

  • 1

    Update react-native to the latest version 🚀

    Version 0.48.0 of react-native just got published.

    Dependency react-native
    Current Version 0.42.3
    Type devDependency

    The version 0.48.0 is not covered by your current version range.

    Without accepting this pull request your project will work just like it did before. There might be a bunch of new features, fixes and perf improvements that the maintainers worked on for you though.

    I recommend you look into these changes and try to get onto the latest version of react-native. Given that you have a decent test suite, a passing build is a strong indicator that you can take advantage of these changes by merging the proposed change into your project. Otherwise this branch is a great starting point for you to work on the update.


    Not sure how things should work exactly?

    There is a collection of frequently asked questions and of course you may always ask my humans.


    Your Greenkeeper Bot :palm_tree:

  • 2

    Cannot read property 'createLTR' of undefined

    Ussing: https://github.com/airbnb/react-dates

    server render

    Cannot read property 'createLTR' of undefined TypeError: Cannot read property 'createLTR' of undefined at Object.createLTR (/usr/src/app/node_modules/react-with-styles/lib/ThemedStyleSheet.js:23:47) at createStyles (/usr/src/app/node_modules/react-with-styles/lib/withStyles.js:105:59) at WithStyles.maybeCreateStyles (/usr/src/app/node_modules/react-with-styles/lib/withStyles.js:200:22) at WithStyles.componentWillMount (/usr/src/app/node_modules/react-with-styles/lib/withStyles.js:134:20) at u.performInitialMount (/usr/src/app/server.bundle.js:15:553194) at u.mountComponent (/usr/src/app/server.bundle.js:15:552366) at Object.mountComponent (/usr/src/app/server.bundle.js:1:96042) at X.mountChildren (/usr/src/app/server.bundle.js:15:559600) at X._createContentMarkup (/usr/src/app/server.bundle.js:15:591579) at X.mountComponent (/usr/src/app/server.bundle.js:15:590247) at Object.mountComponent (/usr/src/app/server.bundle.js:1:96042) at X.mountChildren (/usr/src/app/server.bundle.js:15:559600) at X._createContentMarkup (/usr/src/app/server.bundle.js:15:591579) at X.mountComponent (/usr/src/app/server.bundle.js:15:590247) at Object.mountComponent (/usr/src/app/server.bundle.js:1:96042) at X.mountChildren (/usr/src/app/server.bundle.js:15:559600) at X._createContentMarkup (/usr/src/app/server.bundle.js:15:591579) at X.mountComponent (/usr/src/app/server.bundle.js:15:590247) at Object.mountComponent (/usr/src/app/server.bundle.js:1:96042) at X.mountChildren (/usr/src/app/server.bundle.js:15:559600) at X._createContentMarkup (/usr/src/app/server.bundle.js:15:591579) at X.mountComponent (/usr/src/app/server.bundle.js:15:590247)

  • 3

    Add optional argument to `withStyles` allowing arbitrary data to be passed to the plugin

    I propose modifying withStyles to accept an optional data argument to be passed through to the plugin for the plugin's use. The data argument would be passed to the create method of the interface.

    Implementing this as an arbitrary and optional data argument maintains backwards-compatibility and allows any plugin now or in the future to make use of the feature for its own purposes.

    The use case on which I'm currently working benefits from allowing the user to pass an optional string to withStyles. The purpose of the string is to uniquely identify the component consuming the styles relative to other components also using withStyles.

  • 4

    Update react to the latest version 🚀

    Version 16.5.0 of the react packages was just published.

    Monorepo release group react
    Current Version 15.4.2
    Type devDependency

    This monorepo update includes releases of one or more dependencies which all belong to the react group definition.

    The version 16.5.0 is not covered by your current version range.

    If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update.

    It might be worth looking into these changes and trying to get this project onto the latest version of react.

    If you have a solid test suite and good coverage, a passing build is a strong indicator that you can take advantage of these changes directly by merging the proposed change into your project. If the build fails or you don’t have such unconditional trust in your tests, this branch is a great starting point for you to work on the update.


    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper bot :palm_tree:

  • 5

    `styles` prop validation

    I, with many of us, use your ESLint config preset, which is great. It happens there are rules I don't like and I override them.

    I am not sure about react/forbid-prop-types rule and its setting, which is following:

    'react/forbid-prop-types': ['error', { forbid: ['any', 'array', 'object'] }],
    

    I find it very useful, but hate it when it comes to styles prop. This is no-go with default preset:

    Label.propTypes = {
      styles: PropTypes.object.isRequired,
    };
    

    To validate (and satisfy ESLint) I have to use shape validation rule and write down rules for all styles passed by decorator function - repeated work here. Since styles is defined in very same file and there is very little that could go wrong, I don't feel like paying special attention to that prop.

    How do you validate styles prop at AirBnb?

    Thanks for answer!


    Okay, to be honest I often abuse vague shape validator function, without specifying actual shape of styles prop.

    Label.propTypes = {
      styles: PropTypes.shape().isRequired,
    };
    
  • 6

    Update mocha to the latest version 🚀

    The devDependency mocha was updated from 5.2.0 to 6.0.0.

    This version is not covered by your current version range.

    If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update.


    Release Notes for v6.0.0

    6.0.0 / 2019-02-18

    💥 Breaking Changes

    • #3149: Drop Node.js v4.x support (@outsideris)
    • #3556: Changes to command-line options (@boneskull):
      • --grep and --fgrep are now mutually exclusive; attempting to use both will cause Mocha to fail instead of simply ignoring --grep
      • --compilers is no longer supported; attempting to use will cause Mocha to fail with a link to more information
      • -d is no longer an alias for --debug; -d is currently ignored
      • #3275: --watch-extensions no longer implies js; it must be explicitly added (@TheDancingCode)
    • #2908: tap reporter emits error messages (@chrmod)
    • #2819: When conditionally skipping in a before hook, subsequent before hooks and tests in nested suites are now skipped (@bannmoore)
    • #627: Emit filepath in "timeout exceeded" exceptions where applicable (@boneskull)
    • #3556: lib/template.html has moved to lib/browser/template.html (@boneskull)
    • #2576: An exception is now thrown if Mocha fails to parse or find a mocha.opts at a user-specified path (@plroebuck)
    • #3458: Instantiating a Base-extending reporter without a Runner parameter will throw an exception (@craigtaub)
    • #3125: For consumers of Mocha's programmatic API, all exceptions thrown from Mocha now have a code property (and some will have additional metadata). Some Error messages have changed. Please use the code property to check Error types instead of the message property; these descriptions will be localized in the future. (@craigtaub)

    📠 Deprecations

    These are soft-deprecated, and will emit a warning upon use. Support will be removed in (likely) the next major version of Mocha:

    • -gc users should use --gc-global instead
    • Consumers of the function exported by bin/options should now use the loadMochaOpts or loadOptions (preferred) functions exported by the lib/cli/options module

    Regarding the Mocha class constructor (from lib/mocha):

    • Use property color: false instead of useColors: false
    • Use property timeout: false instead of enableTimeouts: false

    All of the above deprecations were introduced by #3556.

    mocha.opts is now considered "legacy"; please prefer RC file or package.json over mocha.opts.

    🎉 Enhancements

    Enhancements introduced in #3556:

    • Mocha now supports "RC" files in JS, JSON, YAML, or package.json-based (using mocha property) format

      • .mocharc.js, .mocharc.json, .mocharc.yaml or .mocharc.yml are valid "rc" file names and will be automatically loaded
      • Use --config /path/to/rc/file to specify an explicit path
      • Use --package /path/to/package.json to specify an explicit package.json to read the mocha prop from
      • Use --no-config or --no-package to completely disable loading of configuration via RC file and package.json, respectively
      • Configurations are merged as applicable using the priority list:
        1. Command-line arguments
        2. RC file
        3. package.json
        4. mocha.opts
        5. Mocha's own defaults
      • Check out these example config files
    • Node/V8 flag support in mocha executable:

      • Support all allowed node flags as supported by the running version of node (also thanks to @demurgos)
      • Support any V8 flag by prepending --v8- to the flag name
      • All flags are also supported via config files, package.json properties, or mocha.opts
      • Debug-related flags (e.g., --inspect) now imply --no-timeouts
      • Use of e.g., --debug will automatically invoke --inspect if supported by running version of node
    • Support negation of any Mocha-specific command-line flag by prepending --no- to the flag name

    • Interfaces now have descriptions when listed using --interfaces flag

    • Mocha constructor supports all options

    • --extension is now an alias for --watch-extensions and affects non-watch-mode test runs as well. For example, to run only test/*.coffee (not test/*.js), you can do mocha --require coffee-script/register --extensions coffee.

    • #3552: tap reporter is now TAP13-capable (@plroebuck & @mollstam)

    • #3535: Mocha's version can now be queried programmatically via public property Mocha.prototype.version (@plroebuck)

    • #3428: xunit reporter shows diffs (@mlucool)

    • #2529: Runner now emits a retry event when tests are retried (reporters can listen for this) (@catdad)

    • #2962, #3111: In-browser notification support; warn about missing prereqs when --growl supplied (@plroebuck)

    🐛 Fixes

    📖 Documentation

    🔩 Other

    Commits

    The new version differs by 209 commits ahead by 209, behind by 39.

    • 42303e2 Release v6.0.0
    • a553ca7 punctuation updates for changelog v6.0.0
    • c710792 grammar updates for changelog v6.0.0
    • 9f9293a update changelog for v6.0.0
    • a540eb0 remove "projects" section from MAINTAINERS.md [ci skip]
    • 52b5c42 Uppercased JSON reporter name in describe title (#3739)
    • 82307fb Fix .globals to remove falsy values (#3737)
    • 56dc28e Remove unnecessary post-processing code having no effect; closes #3708 (#3733)
    • 16b4281 Documentation updates (#3728)
    • 5d9d3eb Update nyc
    • 118c9ae Refactor out usages of Suite#_onlyTests and Suite#_onlyTests (#3689) (#3707)
    • 0dacd1f Add ability to unload files from require cache (redux) (#3726)
    • 66a52f2 update release steps [ci skip]
    • 45ae014 Refactor lookupFiles and files (#3722)
    • 94c9320 fix --reporter-option to allow comma-separated options; closes #3706

    There are 209 commits in total.

    See the full diff

    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper bot :palm_tree:

  • 7

    Update react to the latest version 🚀

    Version 15.6.2 of react just got published.

    Dependency react
    Current Version 15.4.2
    Type devDependency

    The version 15.6.2 is not covered by your current version range.

    Without accepting this pull request your project will work just like it did before. There might be a bunch of new features, fixes and perf improvements that the maintainers worked on for you though.

    I recommend you look into these changes and try to get onto the latest version of react. Given that you have a decent test suite, a passing build is a strong indicator that you can take advantage of these changes by merging the proposed change into your project. Otherwise this branch is a great starting point for you to work on the update.


    Not sure how things should work exactly?

    There is a collection of frequently asked questions and of course you may always ask my humans.


    Your Greenkeeper Bot :palm_tree:

  • 8

    TypeError: Super expression must either be null or a function, not undefined

    I am getting this error after upgrading to webpack v4. Strangely this happens only in the prod build and not in dev build.

    This is the stack-trace in browser console:

    TypeError: Super expression must either be null or a function, not undefined
    bundle-f82b2570e6fa0145fdb8.js:22:54086
    n.withStyles/</n</<
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:22:54086
    n.withStyles/</n<
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:22:54066
    n.withStyles/<
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:22:53698
    <anonymous>
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:36:433740
    t
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:1:105
    <anonymous>
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:84:260717
    t
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:1:105
    <anonymous>
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:84:263006
    t
    http://localhost:8000/js/bundle-f82b2570e6fa0145fdb8.js:1:105
    

    I am actually using react-dates which is using this library. From stacktrace, I suspect this is where the error is coming from. Also removing react-dates makes the error to go away.

    Here is my entire webpack config: https://gist.github.com/tejasbubane/9ae4d2e099bef97b3b118f99a163294e

    Relevant libraries and their versions:

    "react": "^15.6.1",
    "react-dates": "^15.5.3",
    "react-with-styles": "=2.2.0",
    "webpack": "^4.12.0",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-polyfill": "^6.26.0",
    
  • 9

    Receive component props in decorator

    Receive props passed to component in decorator function in order to create style definition.

    Example:

    function Avatar({ styles }) {
      return <Image style={styles.image} />
    }
    
    const AvatarWithStyle = withStyles(({ color }, ownProps) => ({
      image: {
        width: ownProps.imageSize,
        height: ownProps.imageSize,
        borderRadius: ownProps.imageSize / 2,
      },
    }))(Avatar);
    

    Will pay more attention later in order to discover whether it's possible with existing implementation.

  • 10

    Clear performance marks before setting

    I suppose that current behaviour of marking performance call freeze in Firefox in development. https://github.com/airbnb/react-dates/issues/1359 https://github.com/airbnb/react-dates/issues/1442

  • 11

    Update babel-preset-airbnb to the latest version 🚀

    The devDependency babel-preset-airbnb was updated from 2.6.0 to 3.0.0.

    This version is not covered by your current version range.

    If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update.


    Find out more about this release.

    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper bot :palm_tree:

  • 12

    Add testing on React 17, once Enzyme has an adapter for it

    In https://github.com/airbnb/react-with-styles/pull/246 we bumped our peer deps to React 16.3 || 17. Enzyme doesn't yet have an adapter for React 17, https://github.com/enzymejs/enzyme/pull/2430, but once they do we should add testing for it.

  • 13

    Context provider does not provide the interface

    I'm trying to use v4 with SSR and running into this issue. Without manually registering the interface I'm getting an error. See more details of this issue in the Next.js PR I have open:

    https://github.com/zeit/next.js/pull/13193

  • 14

    Update babel-preset-airbnb to the latest version 🚀


    ☝️ Important announcement: Greenkeeper will be saying goodbye 👋 and passing the torch to Snyk on June 3rd, 2020! Find out how to migrate to Snyk and more at greenkeeper.io


    The devDependency babel-preset-airbnb was updated from 4.5.0 to 5.0.0.

    This version is not covered by your current version range.

    If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update.


    Publisher: milesj License: MIT

    Find out more about this release.


    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper bot :palm_tree:

  • 15

    Update mocha to the latest version 🚀

    The devDependency mocha was updated from 5.2.0 to 7.1.0.

    This version is not covered by your current version range.

    If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update.


    Publisher: juergba License: MIT

    Release Notes for v7.1.0

    7.1.0 / 2020-02-26

    🎉 Enhancements

    #4038: Add Node.js native ESM support (@giltayar)

    Mocha supports writing your test files as ES modules:

    • Node.js only v12.11.0 and above
    • Node.js below v13.2.0, you must set --experimental-modules option
    • current limitations: please check our documentation
    • for programmatic usage: see API: loadFilesAsync()

    Note: Node.JS native ECMAScript Modules implementation has status: Stability: 1 - Experimental

    🐛 Fixes

    📖 Documentation

    🔩 Other

    Commits

    The new version differs by 381 commits ahead by 381, behind by 39.

    • 09b948b Release v7.1.0
    • d43092e update CHANGELOG for v7.1.0 [ci skip]
    • 57be455 Add support for Node.JS native ES modules (#4038)
    • a995e33 Fix: programmatic API cannot access retried test objects (#4181)
    • ac12f2c Browser: fix 'allowUncaught' handling (#4174)
    • 2ff1cb2 uncaughtException: refactor, move and add tests
    • b431609 docs: update browser options
    • 883ae4b ESLint: use 'const' instead of 'let'
    • 2a1b637 Upgrade: ESLint v6.8 (#4138)
    • dbba276 Manage author list in AUTHORS instead of package.json (#4058)
    • d0f04e9 Release v7.0.1
    • 2277958 update CHANGELOG for v7.0.1 [ci skip]
    • 0be3f78 Fix exception when skipping tests programmatically (#4165)
    • c0f1d14 uncaughtException: fix recovery when current test is still running (#4150)
    • 9c10ada Fix backwards compability break for reporterOptions

    There are 250 commits in total.

    See the full diff


    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper bot :palm_tree:

  • 16

    Update jsdom to the latest version 🚀

    The devDependency jsdom was updated from 14.1.0 to 15.2.0.

    This version is not covered by your current version range.

    If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update.


    Publisher: domenic License: MIT

    Release Notes for Version 15.2.0
    • Added basic style inheritance in getComputedStyle() for the 'visibility' property. This sets the foundation for further work on inheritance, cascading, and specificity. (eps1lon)
    • Added shadowRoot.activeElement.
    • Added readystatechange events during document loading.
    • Added a stub for form.requestSubmit(), to match our existing stub for form.submit().
    • Changed el.tabIndex's default value, when no tabindex="" attribute was set, to reflect the updated specification.
    • Changed the exception thrown by el.attachShadow() on something that's already a shadow host, to reflect the updated specification.
    • Fixed the validation logic for <input type="range">.
    • Fixed selectEl.value when no <option> is selected to return the empty string, instead of the value of the first option. (tgohn)
    • Fixed various correctness issues with new FormData(formElement). (brendo)
    • Fixed error messages when parsing XML to include the filename, instead of using "undefined". (papandreou)
    • Fixed the logic for reflected properties to not be affected by overwriting of el.getAttributeNS() or el.setAttributeNS().
    • Set canvas as an optional peerDependency, which apparently helps with Yarn PnP support.
    Commits

    The new version differs by 45 commits.

    • b4bb1c5 Version 15.2.0
    • 0b7dba8 Update dev dependencies
    • a4bcb12 Add inheritance for getComputedStyle() and visibility
    • 974ee53 Add test for querySelector with *= and i
    • e3744f5 Update Travis setup
    • f4706fc Update dependencies
    • 0a759f1 Roll Web Platform Tests
    • 0fd21bb Fix DOMException type for attachShadow
    • 2c53a87 Poll for WebSockets server in WPTs
    • f298acd Update logic to use allowed value step
    • bcb520b Create stub for form.requestSubmit
    • 6b89146 Fix default value for tabIndex IDL attribute
    • 0f09068 Implement DocumentOrShadowRoot
    • abe6a89 Fire readystatechange on the document
    • 699ed6b Fix 's value getter when selectedIndex is -1

      There are 45 commits in total. See the full diff


    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper bot :palm_tree: