Marcus Junius Brutus Marcus Junius Brutus - 1 month ago 8
React JSX Question

require css in React component affects other components too

I have the following

render
in my "main" component:

import ComponentA from './component-a.js';
import ComponentB from './component-b.js';
const App = React.createClass({
render: function() {
return (
<div>
<ComponentA/>
<ComponentB/>
</div>
);
}
});


ComponentA
requires a
css
file. So I have the following in
component-a.js
:

require ('./component-a.css');
const ComponentA = React.createClass({
render: function() {
return (
<div>component a</div>
);
}
});


… whereas
ComponentB
doesn't. So I have the following in
component-b.js
:

const ComponentB = React.createClass({
render: function() {
return (
<div>component b</div>
);
}
});


The
css
file required by
ComponentA
(only) is:

div {
width: 100px;
height: 30px;
border: 1px solid red;
}


Even though it is only
ComponentA
that requires the
css
,
ComponentB
is also affected. This is what gets rendered in the browser:

enter image description here

It seems that all
div
elements in the page are affected by the style required by
ComponentA
. That includes the
div
of the subsequent component
ComponentB
(which does not require the
css
style) as well as the
div
that contains
ComponentA
and
ComponentB
and yet another
div
added by React:

enter image description here


  1. Aren't
    css
    files affecting only the component that requires them? If not, and they are effectively global in effect then what exactly are the semantics of requiring a
    css
    file from a specific component ?

  2. Other than using inline styles and placing everything in JS code, is there a way to compartmentalize CSS files so that they only affect the React component that requires them ? If one were to use class names to achieve that effect there is no guarantee that the class names would be unique when a component is used alongside other components.


Answer

CSS is still loaded into the browser to affect the whole page. The importing of css files is only to modularize your css along with your js, so that when you use your module loader to the fullest, not only are you not loading unnecessary js, you also aren't loading unnecessary css.

EDIT: a video on how Instagram works with module loading:
https://www.youtube.com/watch?v=VkTCL6Nqm6Y&noredirect=1

Your best solution is still to namespace your css. Concerning clashing issues, you could use even more verbose classnames than what I used below like mjb-appname-componentname

Have your ComonentA's render be:

render: function() {
    return (
        <div className="component-a">component a</div>
    );
}

and its css file be

.component-a div {
    width: 100px;
    height: 30px;
    border: 1px solid red;
}

preferably with a css preprocessor like less or sass

.component-a {
    div {
        width: 100px;
        height: 30px;
        border: 1px solid red;
    }
}

extra:

an interesting talk about inline style in js: http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html

a discussion about issues raised by using this inline style method:

https://github.com/callemall/material-ui/issues/4066

Comments