about code ¯\_(ツ)_/¯

Getting started with React

Getting started with anything new is hard. In the frontend development world things are always changing, and changing fast. We’re gonna cut though all the complexity and get you Ninja status asap.

Building a React component

We’re gonna walk though building a React component like the one in the image below. Let’s call it Hacker Card.

Hacker Card

All the files you’ll need for your first React app

hacker-card/
├── package.json
├── webpack.config.js
└── index.js

Beginning with the first file package.json

This file defines all the software you’ll need, it contains a few lists. A list of commands for working with your app and a list of external packages of code to bring in to make your life easier.

You’ll notice some of these packages begin with the word react. And you’re correct those are for that thing you think they’re for.

Then there are some other files that begin with webpack and @babel, those are some serious Ninja weapons that do some wild things to your code, we’ll come to those later. In short don’t worry they’re your friends.

package.json

{
  "name": "HackerCard",
  "version": "0.0.1",
  "description": "A card UI website for hackers",
  "author": "Crazy Kat",
  "license": "MIT",
  "scripts": {
    "start": "./node_modules/.bin/webpack-dev-server --mode=development --hot",
    "build": "./node_modules/.bin/webpack --mode=production"
  },
  "dependencies": {
    "@babel/core": "^7.0.0",
    "@babel/runtime": "^7.0.0",
    "recharts": "^1.1.0"
  },
  "devDependencies": {
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.0",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "styled-components": "^3.4.2",
    "styled-icons": "^2.3.2",
    "styled-system": "^3.0.2",
    "webpack": "^4.1.1",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.5",
    "webpack-node-externals": "^1.7.2"
  }
}

This file has a few sections. The scripts section contains commands for the app. The dependencies section contains names of software packages that will be packaged up along with your app. And finally the devDependencies section which contains names of software packages that are needed only while developingg your app. The little number next to each entry is the version of the software we need to download.

Fine, get to the code already

The first thing you need is Yarn a software tool that downloads and installs everything listed in your package.json. Yarn is what you call a package manager. Yes there are others (NPM) but you’ll use this one because I said so. Also I read someplace it’s faster and more secure ¯\_(ツ)_/¯

Installing Yarn

This is how you do it on a Mac. For other platforms read the install page on the Yarn site. FYI we’re using Homebrew to install it so go get that too if you don’t have it.

$ brew install yarn

Installing React and everything else

Yup, it’s just this one command yarn install and you’re all good to go. You have to run it in the same folder as the package.json file.

$ yarn install

yarn install v1.9.4
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 16.10s.
Yarn technical sidetrack

Yarn will download and install all the packages listed under dependencies and devDependencies into a folder called node_modules. Each of those packages has its own set of dependant packages. In short Yarn has to download a lot of stuff.

Packages are downloaded based on the version you have defined in the package.json file. Package versions are based on something called Semantic versioning. What that means is that a version is made up of three numbers seperated by a period (Eg. 2.5.1)The first number 2 is the major version the second 5 the minor and the third 1 is the patch version.

Specifying only two numbers like 2.5 (2.5.x) or using a tilda prefix like ~2.5.1 means Yarn will only download the latest patch version updates for that package. If say version 3.4.1 was released then Yarn will ignore it.

Using a carrot prefix ^2.5.1 or a single digit 2 (2.x) means that the latest update upto the latest minor version will be downloaded for the package. And using a * or x means the latest major version will be downloaded. This is not recommended as it can break your existing app. Major updates mean big changes that could break your current usecase.

After Yarn is done downloading all the listed packages and their dependant packages it will create a file called yarn.lock which contains all version of each package it downloaded.

It’s time to code! 🎉

Sorry, I’m just messing with you we have one last thing to get though before we hit the code. It’s the other config file in our app called webpack.config.js

Honestly, first time I saw the Webpack config file I was like ಠ_ಠ. Trust me once you learn more you’ll love it and Webpack will be your friend. It will help you in all kinds of wonderful ways.

Webpack

When I first tried to learn Webpack I looked up it’s website. The only description I could find was that it’s simple and that it bundles my scripts. Great now I only have to figure out why I need to bundle my scripts.

At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles. A

― Webpack documentation

ಠ_ಠ

Ok, I did the Googling for you so let me try and explain it. Webpack is a tool that takes files from your app and processes them into a single file. This single file loads faster over the Internet and is in a format that web browsers can understand.

Webpack technical sidetrack

React applications are written in a new version of Javascript (JS) called ES6/ES7 (Ecmascript). Also HTML called JSX is also mixed into the JS code of the app. Web browsers like Chrome, Firefox, Safari, etc cannot understand any of this they only understand the old version of Javascript called ES5.

This is where Webpack comes in, it takes all of this new age stuff and converts it into something the browser understands. This final output of Webpack is called a bundle and will run on almost all browsers. This in short is why you need Webpack for React apps.

Webpack does its work using modules. Babel is one of these modules that’s responsible for converting JSX code that React apps use into plain old Javascript that browsers understand. Babel itself has more modules that help convert newer Javascript features into code that the browser understands. In short you can use all kinds of cool new JS features and JSX while coding your React app and Babel ensures it will all work in all browser. Babel is called a transpiler.

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  entry: path.resolve(__dirname, './index.js'),
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index.js'
  },
  devServer: {
    contentBase: './dist'
  },
  plugins: [
    new HtmlWebpackPlugin({ title: 'Hacker Card', inject: 'body' })
  ],
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      loader: 'babel-loader',
      options: {
        presets: [
        '@babel/env',
        '@babel/react',
        ],
        plugins: [
        '@babel/proposal-object-rest-spread',
        '@babel/proposal-class-properties',
        '@babel/transform-runtime',
        ],
        babelrc: false,
      }
    },
    {
      test: /\.css$/,
      use: [
      'style-loader', 
      'css-loader'
      ]
    }]
  }
};

Understanding webpack.config.js

  entry: path.resolve(__dirname, './index.js'),
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index.js'
  },
  ...

The entry field tells Webpack where it can find the main file of your app. The output fields points to where Webpack will place the final built bundles.

  devServer: {
    contentBase: './dist'
  },
  ...

These three fields are related to running a local server while developing your app. Webpack will wait for any code changes, rebuild and serve your app to the local web browser running on your laptop (or desktop).

In our app this development server is started with the yarn start command. Keep in mind it serves your app directly from memory so it won’t save any bundles to disk. If you need to build and save bundles to disk use yarn build but you don’t need that right now.

  plugins: [
    new HtmlWebpackPlugin({ title: 'Hacker Card', inject: 'body' })
  ],
  ...

Plugins are what make Webpack so great. You add plugins and get all kinds of new capabilties. Lets see how a plugin helps us. Most React app have a HTML file that then links to the React app using the SCRIPT tag. You won’t find one in our app since we use a plugin to generate one as needed (HtmlWebpackPlugin)

 module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel-loader',
        options: {
          ...
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
};
...

This above section is how you list the Webpack modules you want to run your app though to generate those bundles. In this case we have three “babel-loader”, “style-loader” and “css-loader”

The entry for each module uses test and exclude to pick files to process and those to ignore. It then runs the defined loader on those files. Or there is use to run multiple loaders on a file. Loaders are Webpack modules and they each have their own set of options.

We are now ready to code.

I couldn’t wait to get done with that, now onto more fun stuff. The app we are trying to build here is called Hacker Card it’s your own personal website designed to be a small card.

Below is a complete React app, this is not our Hacker Card app as yet it’s just a simple one that displays Hello World. I know it’s cliche but come on I know you were expecting it :-)

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';

const App = () => (<h1>Hello World</h1>);

ReactDOM.render(<App />, document.body);

Launch your app

The yarn start command will now launch a development server to build and launch your app locally on your machine. You are free to continue to add code to your app Webpack will automatically rebuild your app everytime.

$ 
yarn start
yarn run v1.9.4
$ ./node_modules/.bin/webpack-dev-server --mode=development --hot
ℹ 「wds」: Project is running at http://localhost:8080/

... blah ... blah ... blah

ℹ 「wdm」: Compiled successfully.

You should see a big bold “Hello World” that means everything is awesome. And we are now ready to start working on our Hacker Card app code. ^_^

Take a quick break

Just thought you’d like a little break. Grab some tea and feast your eyes on Karl the fog rolling over San Francisco. From here on it’s all code.

San Francisco

Photo by Patrik Göthe on Unsplash

The Hacker Card component

This app is built using something called styled-components and pure-components. A styled-component gives each component it’s own CSS style which can be customised with themes. And a pure-components means that the components don’t have their own state. In short it has no memory of it’s own and are pretty dumb which is good. I’ll explain later.

Let’s look at a React component

const Card = styled.div`
  width: 650px;
  height: 200px
  background-color: yellow;
  ...
`

This is a styled-component, it’s also a pure-component. It is an html DIV element of a fixed size and a yellow background. You might see other examples on the internet that show a more basic React component but I believe styled components is where you should start.

ReactDOM.render(<Card/>, document.body);

This one line will render the component named Card onto an webpage. This will result in a big a yellow rectangle in the browser.

const Image = ( props ) => (
  <div>
  <img src={props.src} />
  <Circle style={{ bottom: '70px', left: '-20px' }}>
    <Fingerprint size='60' />
  </Circle>
  </div>
)

Components can be made up of other components. This component is composed of a DIV, IMG, Circle and Fingerprint component. As you can see mixing plain-old html tags with components is allowed.

There are a couple questions that come to mind here what are all those single and double braces and how does this Image component know what image to display.

Those are great questions. Components get their data from properties (props) they’re read-only and used to pass any type of value into a component such as a number, string, list, object, etc.

And src={props.src} passes the value in props.src down into the IMG child component. In short our Image component will get it’s image link from this property called src.

The double braces for style is the same as the above except we are passing an entire object to the style property not just a single value. In Javascript objects have braces around them so those along with the brances for the style property itself make two sets of braces.

For size we use single quotes to pass a single fixed string value. If size only accepted numbers then you would have had to use braces size={60}

Managing your apps data sidetrack

One does not just use React cause components. The reason React exists is to manage data. Apps are data rich environments. Think of the Twitter website, tweets are flowing in at the same time you might suddently get a direct message and existing tweets are getting new Likes or Retweets in short so much is going on. And of this is driven by data or generating it’s own data.

Try managing all of that while updating the right things on the webpage. A new Like means you have to find the tweet update it’s Like count, maybe change the color of the little heart icon and maybe even put a badge on the top bar notifying the user something happened.

When you use React this data flows from the top where it’s fetched down into each component via properties. And each component knows how to update itself based on this data. The tweet component would know to increase the Like count and change the heart color. Properties are read-only they only bring data into components.

For data flowing out from the component such as letting everyone know the user just clicked the Like button React uses Events.

React apps keep all the data in one single place called State this makes it easy to wrap your head around what’s going on. And all changes to this state filters down to the right components.

We’ll get into this state and event stuff in the next part of this guide.

import React from 'react';
import ReactDOM from 'react-dom';
import { BarChart, Bar } from 'recharts'
...

Import is the Javascript way to include and make use of external code. In this case we obviously have to import React and ReactDOM both of which together give us the React framework.

The { BarChart, Bar } import statement imports only the BarChart and Bar component from a package called recharts.

Bring it all together now

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';

import styled from 'styled-components'
import { BarChart, Bar } from 'recharts'

import { Fingerprint, Star } from 'styled-icons/material'
import { Github } from 'styled-icons/fa-brands'

const Card = styled.div`
  width: 650px;
  height: 200px
  border-radius: .2em;
  box-shadow: -1px 1px 5px 3px #e8e8e8;
  font-size: 20px;
  font-family: -apple-system,helvetica neue;
  display: flex;
  overflow: hidden;

  &:hover { opacity: 0.9; };
  & h3, & p { margin: 0px; }
  & .image { width: 200px; overflow hidden; }
`
const Circle = styled.div`
  position: relative;
  height: 70px;
  width: 70px;
  border-radius: 50%;
  background-color: white;
  display: flex;
  align-items: center;
  align-content: center;
  justify-content: center;
`

const Image = (props) => (
  <div className='image'>
  <img src={props.src} height={200} />
  <Circle style={{ bottom: '70px', left: '-20px' }}>
    <Fingerprint size='60' />
  </Circle>
  </div>
)

const InfoWrap = styled.div`
  display: flex; 
  flex-direction: column;
  justify-content: space-between;
  padding: 0.2em 0.5em;
  overflow: hidden;

  & .name { font-size: 23px; }
  & .title { color: #444; }
`

const Info = (props) => (
  <InfoWrap>
  <div>
    <h3 className='name'>{props.name}</h3>
    <p className='title'>{props.title}</p>
  </div>
  <BarChart width={360} height={100} data={props.data}>
    <Bar dataKey='y' fill='#CEEEAE' />
  </BarChart>
  </InfoWrap>
)

const LinksWrap = styled.div`
  display: flex; 
  flex-direction: column;
  justify-content: start;
  padding: 0.5em 1em;
  overflow: hidden;
  color: #666;
  border-left: 1px solid #f3f3f3;
`

const Links = (props) => (
  <LinksWrap>
    <Github size='40' />
    <Star size='40' />
  </LinksWrap>
)

const profile = {
  image: 'https://avatars3.githubusercontent.com/u/832235?s=200&v=4',
  name: 'Acid Burn',
  title: 'React Hacker Extraordinaire',
  hacking: [
    {x: 'Sun', y: 20},
    {x: 'Mon', y: 30},
    {x: 'Tue', y: 40},
    {x: 'Wed', y: 20},
    {x: 'Thu', y: 40},
    {x: 'Fri', y: 25},
    {x: 'Sat', y: 5}
  ],
}

const App = () => (
  <Card>
    <Image 
      src={profile.image}/>
    <Info  
      name={profile.name} 
      title={profile.title}
      data={profile.hacking}
    />
    <Links />
  </Card>
);

ReactDOM.render(<App />, document.body);

One more time

const App = () => (
  <Card>
    <Image 
      src={profile.image}/>
    <Info  
      name={profile.name} 
      title={profile.title}
      data={profile.hacking}
    />
    <Links />
  </Card>
);

ReactDOM.render(<App />, document.body);

And that’s our final Hacker Card app. We used all the components we previously built Card, Image, Info and Links to create it.

We used a single file but normally we would use one file per component unless they’re really small like in this case.

To built a real app or as the cool kids call it Single Page App we would need multiple views (pages) and a router to decide which one to show based on the URL path. We would even need a way to fetch real data and finally host the app somewhere so the world can use it.

😎 I’ll cover all of this and more in the next part of this series.

What now?

Well, you’re now on your way to React badass status. You know how to setup a new react app, what components are and how you can create them.

Try this example

I encourage you to try it on your own. It’s pretty cool to see it all come together and have a nice component show up in your browser. Also try changing the code make it your own Hacker Card.

$ git clone https://github.com/dosco/react-examples.git
$ cd react-examples/getting-started
$ yarn install
$ yarn start --open

Follow me at twitter.com/dosco

  • Getting started with React

    Getting started with anything new is hard. In the frontend development world things are always changing, and changing fast. We’re gonna cut though all the complexity and get you Ninja status asap.

  • Data and React components

    The post second in this series on React. We focus on how data flows in and out of a React component and how you can use this data to connect multiple components together to build an app.

  • Building larger apps in React

    Having multiple pages in an app is pretty common. Take for example the Amazon app which has products and when you click one you get a detailed look at it. You’re gonna need to know how to build a React app with multiple pages so follow along.

  • Fetching Data in React

    Every React app needs to work with remote data. In this article we’ll walk though how you can make your React components talk to APIs and work with data.

  • Common Frontend Concepts

    React and the rest of the frontend development world is full of new terms. Anyone new can quickly feel overwhealmed. I’m going to try and explain the most popular terms that you will come across when working with React. Think of this as a glossary of things you will come across.