React for Data Visualization
Student Login

Show a Preloader

Preloader screenshot

Our preloader is a screenshot of the final result. Usually you'd have to wait until the end of the project to make that, but I'll just give you mine. Starting with the preloader makes sense for two reasons:

  1. It's nicer than looking at a blank screen while data loads
  2. It's a good sanity check for our environment

We're using a screenshot of the final result because the full dataset takes a few seconds to load, parse, and render. It looks better if visitors see something informative while they wait.

React Suspense is about to make building preloaders a whole lot better. Adapting to the user's network speed, built-in preload functionality, stuff like that. More on that in the chapter on React Suspense and Time Slicing.

Make sure you've installed all dependencies and that npm start is running.

We're building our preloader in 4 steps:

  1. Get the image
  2. Make the Preloader component
  3. Update App
  4. Load Bootstrap styles in index.js

Step 1: Get the image

Download my screenshot from Github and save it in src/images/preloader-screenshot.png. It goes in the src/images/ directory because we're going to import it in JavaScript (which makes it part of our source code), and I like to put non-JavaScript files in assets. Keeps the project organized.

Step 2: Preloader component

Our Preloader is a small component that pretends it's the App and renders a static title, description, and a screenshot of the end result. It goes in src/components/Preloader.js.

We'll put all of our components in src/components/.

We start the component off with some imports, an export, and a functional stateless component that returns an empty div element.

// src/components/Preloader.js
import React from "react"
import PreloaderImg from "../images/preloader-screenshot.png"
const Preloader = () => <div className="App container"></div>
export default Preloader

We import React (which we need to make JSX syntax work) and the PreloaderImg for our image. We can import images because of the Webpack configuration that comes with create-react-app. The webpack image loader returns a URL that we put in the PreloaderImg constant.

At the bottom, we export default Preloader so that we can use it in App.js as import Preloader. Default exports are great when your file exports a single object. Named exports when you want to export multiple items. You'll see that play out in the rest of this project.

The Preloader function takes no props (because we don't need any) and returns an empty div. Let's fill it in.

// src/components/Preloader.js
const Preloader = () => (
<div className="App container">
<h1>The average H1B in tech pays $86,164/year</h1>
<p className="lead">
Since 2012 the US tech industry has sponsored 176,075 H1B work visas. Most
of them paid <b>$60,660 to $111,668</b> per year (1 standard deviation).{" "}
<span>
The best city for an H1B is <b>Kirkland, WA</b> with an average
individual salary <b>$39,465 above local household median</b>. Median
household salary is a good proxy for cost of living in an area.
</span>
</p>
<img src={PreloaderImg} style={{ width: "100%" }} alt="Loading preview" />
<h2 className="text-center">Loading data ...</h2>
</div>
)

A little cheating with grabbing copy from the future, but that's okay. In real life you'd use some temporary text, then fill it in later.

The code itself looks like HTML. We have the usual tags - h1, p, b, img, and h2. That's what I like about JSX: it's familiar. Even if you don't know React, you can guess what's going on here.

But look at the img tag: the src attribute is dynamic, defined by PreloaderImg, and the style attribute takes an object, not a string. That's because JSX is more than HTML; it's JavaScript. Think of props as function arguments – any valid JavaScript fits.

That will be a cornerstone of our project.

Step 3: Update App

We use our new Preloader component in App – src/App.js. Let's remove the create-react-app defaults and import our Preloader component.

// src/App.js
import React from "react"
// Delete the line(s) between here...
import logo from "./logo.svg"
import "./App.css"
// ...and here.
// Insert the line(s) between here...
import Preloader from "./components/Preloader"
// ...and here.
class App extends React.Component {
// Delete the line(s) between here...
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
)
}
// ...and here.
}
export default App

We removed the logo and style imports, added an import for Preloader, and gutted the App class. It's great for a default app, but we don't need that anymore.

Let's define a default techSalaries state and render our Preloader component when there's no data.

// src/App.js
function App() {
const [techSalaries, setTechSalaries] = useState([])
if (techSalaries.length < 1) {
return <Preloader />
} else {
return <div className="App"></div>
}
}

Nowadays we can define properties directly in the class body without a constructor method. It's not part of the official JavaScript standard yet, but most React codebases use this pattern.

Properties defined this way are bound to each instance of our components so they have the correct this value. Late you'll see we can use this shorthand to neatly define event handlers.

We set techSalaries to an empty array by default. In render we use object destructuring to take techSalaries out of component state, this.state, and check whether it's empty. When techSalaries is empty our component renders the preloader, otherwise an empty div.

If your npm start is running, the preloader should show up on your screen.

Preloader without Bootstrap styles

Hmm… that's not very pretty. Let's fix it.

Step 4: Load Bootstrap styles

We're going to use Bootstrap styles to avoid reinventing the wheel. We're ignoring their JavaScript widgets and the amazing integration built by the react-bootstrap team. Just the stylesheets please.

They'll make our fonts look better, help with layouting, and make buttons look like buttons. We could use styled components, but writing our own styles detracts from this tutorial.

We load stylesheets in src/index.js.

// src/index.js
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
// Insert the line(s) between here...
import "bootstrap/dist/css/bootstrap.css"
// ...and here.
ReactDOM.render(<App />, document.getElementById("root"))

Another benefit of Webpack: import-ing stylesheets. These imports turn into <style> tags with CSS in their body at runtime.

This is also a good opportunity to see how index.js works to render our app πŸ‘‡

  1. loads App and React
  2. loads styles
  3. Uses ReactDOM to render <App /> into the DOM

That's it.

Your preloader screen should look better now.

Preloader screenshot

If you don't, try comparing your changes to this diff on Github.

Previous:
176,113 tech salaries visualized – a dataviz dashboard
Next:
Load and parse your data (9:45)
Created by Swizec with ❀️