- Basic
- Accessing the theme inside the styled component
- Accessing the theme without a styled component
- The inner component
- The inner ref
- Decorators
- Injection order
- Usage with TypeScript
React-JSS wraps your component with a higher-order component.
It injects a classes prop, which is a simple map of rule names and generated class names.
Try it out in the playground.
import React from 'react'
import {render} from 'react-dom'
import withStyles from 'react-jss'
// Create your Styles. Remember, since React-JSS uses the default preset,
// most plugins are available without further configuration needed.
const styles = {
myButton: {
color: 'green',
margin: {
// jss-plugin-expand gives more readable syntax
top: 5, // jss-plugin-default-unit makes this 5px
right: 0,
bottom: 0,
left: '1rem'
},
'& span': {
// jss-plugin-nested applies this to a child span
fontWeight: 'bold' // jss-plugin-camel-case turns this into 'font-weight'
}
},
myLabel: {
fontStyle: 'italic'
}
}
// Define the component using these styles and pass it the 'classes' prop.
// Use this to assign scoped class names.
const Button = ({classes, children}) => (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
// Finally, inject the stylesheet into the component.
const StyledButton = withStyles(styles)(Button)
// You can also export the component with
// export default withStyles(styles)(Button)
const App = () => <StyledButton>Submit</StyledButton>
render(<App />, document.getElementById('root'))The above code will compile to
<div id="root">
<button class="Button-myButton-1-25">
<span class="Button-myLabel-1-26">
Submit
</span>
</button>
</div>and
.Button-myButton-1-25 {
color: green;
margin: 5px 0 0 1rem;
}
.Button-myButton-1-25 span {
font-weight: bold;
}
.Button-myLabel-1-26 {
font-style: italic;
}The theme will not be injecting into the wrapped component.
To inject the theme into the wrapped component, pass the injectTheme option to withStyles.
import React from 'react'
import withStyles from 'react-jss'
const DeleteIcon = () => null
const Button = ({classes, children, theme}) => (
<button className={classes.button}>
<span className={classes.label}>{children}</span>
{theme.useIconButtons && <DeleteIcon />}
</button>
)
const styles = theme => ({
button: {
background: theme.colorPrimary
},
label: {
fontWeight: 'bold'
}
})
const StyledButton = withStyles(styles, {injectTheme: true})(Button)In case you need to access the theme but not render any CSS, you can also use withTheme. It is a Higher-order Component factory which takes a React.Component and maps the theme object from context to props. Read more about withTheme in theming's documentation.
import React from 'react'
import {withTheme} from 'react-jss'
const Button = withTheme(({theme}) => <button>I can access {theme.colorPrimary}</button>)import withStyles from 'react-jss'
const InnerComponent = () => null
const StyledComponent = withStyles({})(InnerComponent)
console.log(StyledComponent.InnerComponent) // Prints out the inner component.To get a ref to the inner element, use the ref prop.
We will forward the ref to the inner component.
import React from 'react'
import withStyles from 'react-jss'
const InnerComponent = () => null
const StyledComponent = withStyles({})(InnerComponent)
const App = (
<StyledComponent
ref={ref => {
console.log(ref)
}}
/>
)Beware that decorators are stage-2 proposal, so there are no guarantees that decorators will make its way into language specification. Do not use it in production. Use it at your own risk and only if you know what you are doing.
You will need babel-plugin-transform-decorators-legacy.
import React, {Component} from 'react'
import withStyles from 'react-jss'
const styles = {
button: {
backgroundColor: 'yellow'
},
label: {
fontWeight: 'bold'
}
}
@withStyles(styles)
class Button extends Component {
render() {
const {classes, children} = this.props
return (
<button className={classes.button}>
<span className={classes.label}>{children}</span>
</button>
)
}
}
export default ButtonInjection of style tags happens in the same order as the withStyles() invocation.
Source order specificity is higher the lower style tag is in the tree. Therefore you should call withStyles of components you want to override first.
Example
import React from 'react'
import withStyles from 'react-jss'
const labelStyles = {}
const buttonStyles = {}
// Will render labelStyles first.
const Label = withStyles(labelStyles)(({children}) => <label>{children}</label>)
const Button = withStyles(buttonStyles)(() => (
<button>
<Label>my button</Label>
</button>
))React JSS includes first class support for TypeScript. React JSS provides
a WithStyles type which adds types for all of the injected props.
To use it, simply extend your existing props interface with
WithStyles<typeof styles>, where styles is your styles object.
Note: To use WithStyles you must use react-jss version 10 or higher.
Example
import * as React from 'react'
import withStyles, {WithStylesProps} from 'react-jss'
const styles = {
button: {
backgroundColor: 'yellow'
},
label: {
fontWeight: 'bold'
}
}
interface IProps extends WithStylesProps<typeof styles> {
children: React.ReactNode
}
const Button: React.FunctionComponent<IProps> = ({classes, children}) => (
<button className={classes.button}>
<span className={classes.label}>{children}</span>
</button>
)
export default withStyles(styles)(Button)