React itself does not encumber usage of Heap. However, a number of styling libraries commonly used with React will generate DOMs which change each time the app is built. This will affect your event definitions since they rely on stable CSS selectors. In this guide, we will go through a number of styling libraries and describe some configuration modifications which will yield a more useful DOM for Heap.
For all of these styling libraries, these configuration changes will result in a DOM with more semantically useful class names. So, once the configuration change is made, please refer to our guide on using semantically useful class names.
Styled Components
Using the default, production-ready configuration for Styled Components, you will get a DOM which is problematic for Heap usage as shown below.
Component
const StyledButton = styled.button`
background-color: #808080;
`;
const StyledComponentsButton = () => <StyledButton>Submit</StyledButton>;
Default Configuration DOM
<button class="sc-AxjAm gIZUvF">Submit</button>
Solution
Per the Styled Components docs, by enabling the displayName
option on the Styled Components babel plugin, babel will prepend the class names in your hierarchy with a stable, semantically useful string. Note that if you are using a zero-configuration project such as a project created using create-react-app, you will have to import from styled-components/macro
instead of styled-components
.
.babelrc Configuration
{
"plugins": [
[
"babel-plugin-styled-components",
{
"displayName": true
}
]
]
}
Resulting DOM with Updated Configuration
<button class="StyledComponentsButton__StyledButton-sc-4joyzr-0 hDrDhu">
Submit
</button>
JSS
Without any extra configuration, JSS will produce a stable class. However, if you enable minify: true as an option on the JSSProvider, you will get a class which is not useful for event definitions.
JSS-styled component
const useStyles = createUseStyles({
button: {
backgroundColor: "#808080",
},
});
const JSSButton = () => {
const classes = useStyles();
return <button className={classes.button}>Submit</button>;
};
Minified Provider
ReactDOM.render(
<React.StrictMode>
<JssProvider id={{ minify: true }}>
<App />
</JssProvider>
</React.StrictMode>,
document.getElementById("root")
);
Minified DOM
<button class="c021">Submit</button>
Solution
By simply omitting minify: true
from your JSSProvider
configuration, you will get a stable DOM for the above Button
component as shown below.
Stable DOM Provider Configuration
ReactDOM.render(
<React.StrictMode>
<JssProvider id={{}}>
<App />
</JssProvider>
</React.StrictMode>,
document.getElementById("root")
);
Stable DOM
<button class="button-0-2-1">Submit</button>
Aphrodite
In production builds, Aphrodite will minify class
names (when NODE_ENV === 'production'
). That means, in production, the following component will yield a minified DOM as shown below.
Component
const styles = StyleSheet.create({
greyButton: {
backgroundColor: '#808080'
}
})
const AphroditeButton = () => (
<button className={css(styles.greyButton)}>Submit</button>
);
Minified DOM
<button class="x34zcx">Submit</button>
Solution
By importing minify
from Aphrodite and calling minify(false)
, the DOM will include a stable class name.
Stable DOM Configuration
import { StyleSheet, css, minify } from 'aphrodite';
minify(false);
const styles = StyleSheet.create({
greyButton: {
backgroundColor: '#808080'
}
})
const AphroditeButton = () => (
<button className={css(styles.greyButton)}>Submit</button>
);
Stable DOM
<button class="greyButton_x34zcx">Submit</button>
Emotion
In production (when NODE_ENV === production
), Emotion will strip the label from the generated class names. By default, the label is the name of the variable that the component is assigned to. This means that the resulting DOM will be minified and unstable as shown below.
Component
const StyledButton = styled.button`
background-color: #808080
`;
const EmotionButton = () => <StyledButton>Submit</StyledButton>;
Minified DOM
<button class="css-3wf5vo">Submit</button>
Solution
To keep a stable class name in your DOM, Emotion provides a couple of options, both of which rely on the use of their babel plugin. The easiest fix is to specify ”autoLabel”: true
in your .babelrc
. To tweak the format of the label, Emotion provides a setting called labelFormat
which allows you to provide a template based off of the variable name the component is assigned to, the filename of the component, and the directory name of the component. Read more about this setting in Emotion’s documentation.
To use the default label, change the .babelrc
as shown below. Please note that, similar to Styled Components, if you’re using a zero config React project, such as one generated by create-react-app
, you will have to import from one of emotion’s “macro” packages, e.g., import styled from @emotion/styled/macro
.
.babelrc Configuration
{
"plugins": [
"emotion",
{
"autoLabel": false
}
]
}
Resulting DOM with Updated Configuration
<button class="css-1g0i8xt-StyledButton e1a9pd9w0">Submit</button>