Inline Styles

I just completed a React image slider app using Jest for testing and Radium for React inline styles, and I thought I would share my experience so that others who may use the two tools together wouldn’t be surprised when certain things took place.

As some of you may already know, there is a certain amount of configuration involved in making Radium work for you.

First you have to install it. I use npm (node package manager), so I first typed the command npm install radium --save in iTerm2 (Terminal).

Next I imported it into the Components in which I wanted to include CSS in JS (inline styles). I did it like so:

// At top of Footer.js (Class Component)

import Radium from 'radium';

// At bottom of Footer.js
export default Radium(Footer);

Then, in (what I thought should be) my HOC/Container, I added the following:

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Radium, {StyleRoot} from 'radium';
import App from './App';
import './style/style.scss';

ReactDOM.render(
	<StyleRoot><App /></StyleRoot>, document.getElementById('root')
);

The StyleRoot Component is needed to enable the use of media queries and CERTAIN pseudo elements. Not all pseudo elements are compatible with Radium. According to the documentation,

Radium supports styling for three browser states that are targeted with pseudo-selectors in normal CSS: :hover, :focus, and :active.

Given my specific styling needs in the projects in which I have used Radium, I haven’t yet had success with pseudo selectors. But then again, I just started using Radium recently. I mostly have used it for inline styles, nested inline styles, and media queries as well as grouping various style objects together in a []. There is much more to the package than that, and I look forward to discovering more and more features!

Radium does not necessarily consider index.js to be your **HOC/Container by default. Usually it will be your App.js Component. I did not even think at first that I would have to wrap my App Component in index.js with the StyleRoot Component. I first went for the following approach:

// App.js

import React, {Component} from 'react';
import Radium from 'radium';
import Header from './components/Header';
import Slider from './components/Slider';
import Footer from './components/Footer';

import photoAug15100332 from '../images/photoAug15100332.jpg';
import photoAug15111608 from '../images/photoAug15111608.jpg';
import photoAug15111623 from '../images/photoAug15111623.jpg';
import photoAug15112130 from '../images/photoAug15112130.jpg';

const sliderData = [
	{
		src: photoAug15100332,
		credits: 'The Beauty'
	},
	{
		src: photoAug15111608,
		credits: 'The Plotter'
	},
	{
		src: photoAug15111623,
		credits: 'The Gazer'
	},
	{
		src: photoAug15112130,
		credits: 'The Ponderer'
	}
];

class App extends Component {
	render() {
		return (
			<StyleRoot>
			<div className='App Site'>
				<Header />
				<div className='Site-content'>
					<Slider slides={sliderData} />
				</div>
				<Footer />
			</div>
			</StyleRoot>
		)
	}
}

export default App;

When I ran npm run serve to start up my development server, I got an error in the console stating that I had to wrap my App Component with the StyleRoot Component. When I looked at my code, I saw that App WAS wrapped with <StyleRoot></StyleRoot>. Thinking that App was NOT my application’s HOC/Container, I proceeded to remove the Radium import and StyleRoot from App.js. Then I imported Radium and {StyleRoot} into index.js and wrapped <App /> with <StyleRoot></StyleRoot>. But that was wrong and unnecessary, even though the application seemed to render properly. Look at the code snippet above and consider why that is the case.

It’s because I forgot to wrap App with Radium()! The following is what I SHOULD have done at the bottom of App.js:

export default Radium(App);

This was partly due to the fact that I ran tests after I had added Radium to my project and got the following warning in my iTerm2 console:

Console

    console.error node_modules/fbjs/lib/warning.js:33
      Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.

This COULD be a valid error related to a React Component. I did receive it when I tried to include a functional Component in App.js. Given the structure of my application and state, I had to change it to a Class Component, and then the error went away. BUT, if all your tests pass without this warning BEFORE you add Radium to your project and then it appears AFTER you add Radium, the error is due to Radium’s wrap around App: Radium(App). After all, Radium() IS a function!

My advice AND my takeaway on using Radium and Jest together in a React project? Do ALL your testing on your code before you add Radium to the picture. That way you know for sure that the warning relates to Radium and NOT to any code related to your Components. I had to remove any trace of Radium in my application before I was able to determine it was Radium() and not my code that triggered the warning.

Happy TDD, inline styles, and React development!

Using Radium