React Fundamentals – ReactJS

I didn’t know what to title this post – I’ve got tons of thoughts about ReactJS. At the time of this post, ReactJS has taken single page apps to another level, well I shouldn’t say another level – it just sounded cool. Yeah there are others out there – I actually like Vue.js, it’s a much lighter version compared to react. And Angular(what version is out now) – I make mention of this framework with a little snark because I’ve wrestled with it many times in the past. At the moment I’m not really a big fan of Angular, sorry Angular but there’s just way too much stuff going on with you. Maybe things will change.

I wanted to make another post dedicated to just my thoughts on ReactJS but then I’ll be overthinking it and then I’ll end up going in circles. So let’s just get on with it.

So I mostly get tasks that are PHP or WordPress related – but recently I was asked to consult on a progressive web application using ReactJS. The app was super clean and snappy, I can tell the developers put extra care in their code. What they needed help with was with optimizing for SEO – basically getting their site crawled by Google bots, indexing and all that. I mean, I’ve dabbled with a good handful of tutorials covering ReactJS – some small apps like a weather app and some two way binding (one of the reasons progressive frameworks are so powerful) with forms. But all I needed to know is that React apps (and friends – Vue.js, Angular) all serve dynamic content on the fly – ok that was totally vague. Basically, content isn’t crawlable. Whoa totally repeating myself.

Ok so I searched the interwebs looking for some insight and recommended this node module specifically designed for challenges like this – React SEO. Yeah of course right, the name says it all. Don’t mean to sound like a douche or anything, but I was just curious why their devs couldn’t find this themselves, all you had to do was google search “react and seo”. Speaking of SEO, I also had to familiarize myself with Google’s fetch console, the tool that actually simulates how Google would read your web application if it had eyes. There’s a lot of nerding out to be done.

I too was curious about this React SEO module. Will it solve their issue? I wanted to find out for myself so I had to quickly find a reliable youtube tutorial – this had to be fresh, I felt tempted to use some react apps I have in my repo to test on but I’m the type that constantly needs to learn something new.

If this module doesn’t solve the issue due to some anomaly, the only other recommendation I have would be to create a condition for the homepage, a special case in which mark up is not rendered dynamically so that at least the homepage is crawlable. Something Google places high value on more than any other page. So at least that’s taken care of at the moment until something better comes out.

I found this tutorial on youtube – React Fundamentals – Full Course for Beginners, it looked solid. So I’m going to dive right in.

We will need the following:

I have NodeJS on my system so I’m good there just need to pull from the repo and then run the following command:

1. Pull from repo using npm (you must have to run sudo)


npm install create-react-app -g

2. Run command


// oh yeah did I forget to mention 
// were creating a TV series app
create-react-app tv-series-app

// navigate into the folder
cd tv-series-app

// run server
npm start

… installation process may take a while.

Yeah.. and then boom we have an actual React App running (whoa, crappy cropping):

The directory stucture all written out, literally. Hey I felt like writing.

React Boiler Plate Directory Structure

Then the codes:


import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App'; // the stuff in App.js, the App Component
import registerServiceWorker from './registerServiceWorker';

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

Were accessing the index.html and looking for the element containing the id of ‘root’. Once we have that, we can do all sorts of stuff using components. All those imports are references to React’s core library (or framework or whatever).

We can mess around with ReactDOM.render() by passing a constant in place of like so:


// I'm thinking this is a simple way of attaching dynamic elements to a root element. 
// But were better off using components
const greeting = React.createElement('h1', {}, 'Hello World!');  

ReactDOM.render(greeting, document.getElementById('root'));
registerServiceWorker();

Components, the App.js Component

Yeah I had to copy paste the entire thing, I found it hard not too. This is a general design pattern with building Components – you have your render() method, JSX and the JSX compiler – Babel.js.


import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

Using JSX and interpolation

With JSX we can do more than create dynamic HTML elements like mix it with some javascript. These are just quick exercises, sort of like stretching out. You’ll need a lot of it when you’re bouncing around a handful of different frameworks written in different languages.


// Using arrow function
// Identical to = function()
const getCurrentDate = () => {
  
  const date = new Date();
  return date.toDateString();

}

const greeting = <h1>Hello World! Current date: {getCurrentDate()}</h1>

ReactDOM.render(greeting, document.getElementById('root'));

Creating our first component in App.js


// Functional component
// Also something to note
// If this function only had one argument
// the parenthesis can be ommited like so:
// const Intro = props => 

// Why am I not using multi line commenting syntax? Next time.

const Intro = (props) => (

  <p className="App-intro">
    Our first functional component
  </p>

);

class App extends Component {

  render() {
      <div className="App">
        <header className="App-header">
          <h1 className="App-title">TV Series List</h1>
        </header>
        <Intro /> // <---- There's that Intro function, it's a component now. 
      </div>
  }

}

Breaking everything, well not everything – into Components

Yeah we don’t want to go crazy with components. Think of what responsibility each components have and if it makes sense. For instance in this tutorial were actually going to create a folder for Components and then we’ll move the Intro (functional component) into it.

Components Folder

Then back on App.js we can import the Intro component, at the very top of the file.


import React, { Component } from 'react';
import Intro from './components/Intro';
import './App.css';

Yeah, you can kind of see how were coupling components based on context and functionality. Moving on…

We can do more stuff with ‘props’ or component properties. We can do something like this –


// In App.js
<Intro message ="Here you can find all of your most loved series" />

Then in Intro/index.js


  <p className="App-intro">
  {props.message}
  </p>

We just accessed the props object. You can add other data types as well – strings, arrays, numbers, booleans, functions etc. Whaaaaat.

State

The data to be rendered, usually an object or an array data type. Yeah other data types as well but objects and arrays are most common.


// a javascript object containing an empty array

// I'm curious if state is built-in reserved keyword?
state = {
  series: []
}

// And then within the render() method
The length of series array - {this.state.series.length} // should output 0

Lifecycle

Mounting and unmounting after a component has loaded. I wish I could write more about this whole mounting thing, but I’m reminded of jQuerys “beforeSend” method when I see this. It’s like, let’s do something like run a function call back after some other process.

So here were updating the series array by adding some elements to the array. When check the length using {this.state.series.length} after 2 seconds, we should be an output of “2”.


componentDidMount() {

  const series = ["Vikings", "Game of Thrones"];

  // takes a function and a delay
  // updates the series object
  setTimeout(() => {
   this.setState({series: series});
  }, 2000);
  );

}

Asynchronous Calls

Okay, I’m more familiar with this one – I actually have a couple existing pet projects where I have to deal with asynchronous calls. Man, I love asynchronous calls – Google wouldn’t be google without it. Asynchronous calls allows for data to be rendered and/or retrieved without loading an entire page again giving your apps a desktop feel, a progress app feel, or a native mobile app feel.

There are more than a handful of methods and libraries that allow apps to make asynchronous, the most popular one is jQuerys $.ajax object, but in the tutorial were working with were going to use “Fetch“.

Run npm install to install this module.


npm install whatwg-fetch --save

// then import it into App/index.js
.. other imports.. <----- Other imported modules
import 'whatwg-fetch'

Back to componentDidMount() we’ll use a real API to pull in data instead of hard coding everything. The API is called TV Maze. Pretty cool API, didn’t even know this existed – I wonder how much data they have about TV shows and how far back they go. If they got everything – that would be nerdgasmic.

Anyway back to the task at hand. Let’s update componentDidMount(). Mount is such an interesting word of choice, I keep thinking about the word mount, it’s getting unnecessarily funny.


componentDidMount() {

  // after fetching
  // we can chain promises by chaining 
  // then methods
  fetch('http://api.tvmaze.com/search/shows?q=Vikings')
    .then(response => response.json())
    .then(json => this.setState({ series: json })) // update series array with API data (instead of hard coded array from earlier

}

To the unappreciative that looks like every day jargon code – but that is some super powerful stuff.

Containers

Containers are a modular pattern used in programming, in this case were using Containers (as the name suggests) to contain or modularize and manage state, or data retrieved, passed around and rendered. This sort of reminds me of the “Model” part in “MVC” (Model, View, Controller) frameworks – and I’m a big fan of MVC’s.

Before we get back to Containers… I skipped an important part and I really don’t want to forget about it. Earlier we actually need to move the App related stuff – App.js, App.css, App.test.js into its own directory, just like we did with Intro. Think of directories like modules, each containing its own compartmentalized set of functions. Naming these directories have to do with context – Components serve as presentational components and Containers serve as state components, that’s how I see it.

At this point this is what the /containers/series/index.js file should look like. Yeah bad lighting at the starbucks I was at and this isn’t a photography blog so just gotta deal with it.

Series Index file

Refactoring the code

Referencing the photo document above, were going to refactor it a bit. As I watching this segment, I had to pause for a minute and think about javascripts onChange event and how powerful it is. I started thinking about one of pet projects, a case where I was working with a list of countries and I wanted to dynamically update a list of states (or regions) depending on what country you chose. All this without reloading the page, yeah dynamic stuff.

Moving the code from componentDidMount() into the onSeriesInputChange function block. So instead of running the api call (fetch) after the series component has loaded, we make a call each time an on change event is fired – super cool.

The state object. Notice we set some new data types to allow for conditions, they sort of work like a light switch.


  state = {
    series: [],
    seriesName: '',
    isFetching: false
  }

That cool event handler called onChange()


  onSeriesInputChange = e => {

      fetch('http://api.tvmaze.com/search/shows?q=${e.target.value}')
      .then(response => response.json())
      .then(json => this.setState({ series: json, isFetching: false }));

  }

Then in the render() function, the JSX code would now look like the below. At this point, the app should be working – able to fetch tv shows as you type in the input field. Yeah I know it’s looking sweet.


    return (
      <div>
        <div>
          <input type="text"
          value={seriesName}
          onChange={this.onSeriesInputChange}
          />
          {
            series.length === 0 && seriesName.trim() === ''
            &&
            <p>Please enter series name into the input</p>

          }
          {
            series.length === 0 && seriesName.trim() !== ''
            &&
            <p>No TV series have been found with this name</p>
          }
          {
            isFetching && <p>Loading...</p>
          }
          {
            !isFetching && <SeriesList list={this.state.series} />
          }
        </div>
      </div>
    )

Images (Loader Component)