Prevent Emotion style injection

43 Views Asked by At

I am using the JsonForms React Component to dynamically generate an HTML form in my web-application. The framework I use does all of the view rendering on the server side, so to include this component I compiled a small react component using npm run build producing a main.js and include it in my app like this:

<html>
  <head>
    ...
    <script type="text/javascript" src="main.js"></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

Functionally, everything works as expected, however on pages that include the React component the CSS styling of other page elements (outside of the component) have changed. When I inspect the computed styles in Chrome I see that there is a <style> tag that has overridden the font-family applied to body:

Illustration of Chrome computed styles

I see that after the page loads the <head> section includes style tags mentioning the "emotion" library that aren't present in the page source sent by the server:

Tags injected into head

I assume that the javascript for my React component has injected additional CSS styles into my page. If I delete the tag "" the styles such as the font-family change are reverted.

How can I figure out where the .css changes that are made by emotion are specified? Is there a way to configure/namespace a component that is styled with emotion to prevent unintended styling of other elements on the page?

For all intents and purposes, the JsonForms component I am adding to my page is the same as the "seed" app provided by the JsonForms library:

import { Fragment, useState, useMemo } from 'react';
import { JsonForms } from '@jsonforms/react';
import Grid from '@mui/material/Grid';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import logo from './logo.svg';
import './App.css';
import schema from './schema.json';
import uischema from './uischema.json';
import {
  materialCells,
  materialRenderers,
} from '@jsonforms/material-renderers';
import RatingControl from './RatingControl';
import ratingControlTester from './ratingControlTester';
import { makeStyles } from '@mui/styles';

const useStyles = makeStyles({
  container: {
    padding: '1em',
    width: '100%',
  },
  title: {
    textAlign: 'center',
    padding: '0.25em',
  },
  dataContent: {
    display: 'flex',
    justifyContent: 'center',
    borderRadius: '0.25em',
    backgroundColor: '#cecece',
    marginBottom: '1rem',
  },
  resetButton: {
    margin: 'auto !important',
    display: 'block !important',
  },
  demoform: {
    margin: 'auto',
    padding: '1rem',
  },
});

const initialData = {
  name: 'Send email to Adrian',
  description: 'Confirm if you have passed the subject\nHereby ...',
  done: true,
  recurrence: 'Daily',
  rating: 3,
};

const renderers = [
  ...materialRenderers,
  //register custom renderers
  { tester: ratingControlTester, renderer: RatingControl },
];

const App = () => {
  const classes = useStyles();
  const [data, setData] = useState<any>(initialData);
  const stringifiedData = useMemo(() => JSON.stringify(data, null, 2), [data]);

  const clearData = () => {
    setData({});
  };

  return (
    <Fragment>
      <div className='App'>
        <header className='App-header'>
          <img src={logo} className='App-logo' alt='logo' />
          <h1 className='App-title'>Welcome to JSON Forms with React</h1>
          <p className='App-intro'>More Forms. Less Code.</p>
        </header>
      </div>

      <Grid
        container
        justifyContent={'center'}
        spacing={1}
        className={classes.container}
      >
        <Grid item sm={6}>
          <Typography variant={'h4'} className={classes.title}>
            Bound data
          </Typography>
          <div className={classes.dataContent}>
            <pre id='boundData'>{stringifiedData}</pre>
          </div>
          <Button
            className={classes.resetButton}
            onClick={clearData}
            color='primary'
            variant='contained'
          >
            Clear data
          </Button>
        </Grid>
        <Grid item sm={6}>
          <Typography variant={'h4'} className={classes.title}>
            Rendered form
          </Typography>
          <div className={classes.demoform}>
            <JsonForms
              schema={schema}
              uischema={uischema}
              data={data}
              renderers={renderers}
              cells={materialCells}
              onChange={({ errors, data }) => setData(data)}
            />
          </div>
        </Grid>
      </Grid>
    </Fragment>
  );
};

export default App;
1

There are 1 best solutions below

0
Bioman On

After slicing away the various pieces of the seed application to determine what piece of code causes the style tag injection I learned that the unwanted styling was coming from the use of <CssBaseline /> (from '@mui/material') in the src/index.tsx:

ReactDOM.render(
  <ThemeProvider theme={theme}>
    <CssBaseline />
    <App />
  </ThemeProvider>,
  document.getElementById('root')
);

https://github.com/eclipsesource/jsonforms-react-seed/blob/7c57180ee581dda8d2336730655ccb5498eed8a2/src/index.tsx#L22

Deleting this tag prevented the Material styles from being applied to the rest of my page.