A long-awaited stable version of JSS v10 is out and here is a summary of what happened. This is a higher-level summary, a full changelog is here and a migration guide here.

It took us almost a year to release this version with much fewer features and improvements than originally planned, because most of the work happens in our spare time and current Open Collective status isn’t usable to pay contributors, not to mention myself.

New hooks-based API for React-JSS

With hooks API, these problems are “gone”, but there is more to it. The new interface gives you better control over data that is passed to the function values.

import React from 'react'
import {createUseStyles} from 'react-jss'
const useStyles = createUseStyles({
myButton: {
padding: props => props.spacing
},
myLabel: props => ({
display: 'block',
color: props.labelColor,
fontWeight: props.fontWeight,
fontStyle: props.fontStyle
})
})
const Button = ({children, ...props}) => {
const classes = useStyles(props)
return (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
}

So why do we need a hook creator function createUseStyles() that returns a hook function useStyles()?

It’s because we want to automate managing Style Sheets for you by integrating them with React’s lifecycle. When component umounts, it removes unused styles from the DOM and keeps the long-term application performance consistent, because CSS attached to the Render Tree is not free of charge.

Notice that you can call useStyles(data) with any data argument, so you have a chance to decide what data goes into function values. For example, you could as well use state or context.

In addition, it gives us better control over Theming:

import React from 'react'
import {createUseStyles, useTheme} from 'react-jss'
const useStyles = createUseStyles({
myButton: {
padding: ({theme}) => theme.spacing
}
})
const Button = ({children, ...props}) => {
const theme = useTheme()
const classes = useStyles({...props, theme})
return (
<button className={classes.myButton}>Test</button>
)
}

Notice that you could also use the theme in your rendering logic or pass anything else as a theme .

Scoped keyframes animations

The new syntax looks like this:

const styles = {
'@keyframes slideRight': {
from: {opacity: 0},
to: {opacity: 1}
},
container: {
animationName: '$slideRight'
}
}

and compiles to

@keyframes keyframes-slideRight-0 {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.container-1 {
animation-name: keyframes-slideRight-0;
}

To get the generated keyframes id from JSS StyleSheet, you can use sheet.keyframes.slideRight .

The full syntax for function values and observables

The solution we ended up with is to make them support full syntax by default (things like media queries, nesting, etc.), but to enable opting out in case you want to reduce the overhead to the minimum:

sheet.update(data, {process: false})

Houdini Typed CSSOM

How is it useful in JSS? It gives you a way to optimize the update performance of CSS values. The point of using Typed CSSOM objects is to be able to change a value without involving a CSS parser.

Here is a simple example that updates a Typed CSSOM value, in a nutshell, it’s this:

const styles = {
button: {
top: data => data.top || 0
}
}
// Create an instance of CSSUnitValue.
const top = CSS.px(20);
// Mutate the value without CSS parsing.
top.value = top.value + 20;
Tell JSS to set the updated value.
update({top})

Monorepo

ESM ready

TypeScript Types

Final Notes

Also a big thanks to BrowserStack for providing a free account, since CSSOM has many cross-browser issues and it wouldn’t be possible to do what we did without testing it in real browsers.

Eng. @webflow, React, CSSinJS and co. Creator of http://cssinjs.org. Stealing ideas is great. Semantics is just meaning. Twitter: https://twitter.com/oleg008

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store