React is a library that only takes care of rendering the view while making sure it's in sync with the state.

React Create App

Zero-configuration setup.

sudo npm i -g create-react-app
create-react-app app-name

It will install:

  • Lightweight development server
  • Webpack (bundler)
  • Babel (transpiler)

It also enables hot module reloading, which means we don't have to re-build and refresh after each change.

Errors

You appear to be offline. Falling back to the local Yarn cache.

sudo apt-get remove yarn && sudo apt-get purge yarn

npm config set registry "https://registry.npmjs.org"

Eject

This will permanently add all the abstracted dependencies in package.json and the config files will appear. This allows detailed configurations.

npm run eject

Hello World

// React object from module.
import React from "react";
import ReactDOM from "react-dom";

const element = <h1>Hello World</h1>; // JSX expression

ReactDOM.render(element, document.getElementById("app"));

JSX

It's syntactic sugar for creating HTML elements with javascript, instead of using templating engines. It's not a string, but an expression.

const element = <h1>Hello World</h1>;

Babel transpiles it into...

var element = React.createElement("h1", null, "Hello World");

Since the compiled JSX makes a call to React.createElement, we need to import React, even if we don't use the object directly.

This returns an Object, a React element, which is part of the virtual-DOM.

The call to the function is the reason why we need one parent element, as Babel gets confused with multiple.

Virtual-DOM

Lightweight in-memory representation of the UI. Instead of re-building the DOM on each change, the virtual DOM sees the changes and it just updates the changed parts in the real DOM.

Whenever the state of the React element object changes...

  • React gets a new React element.
  • Compares it to the previous one to see the changes.
  • Update just the changed parts in the real DOM.

The DOM updating is done by the render() method in the react-dom module. It takes the object returned from JSX and renders the HTML inside the referenced div.

Components

A piece of UI. A javascript class that has some state to be displayed and a render method.

counter.jsx

import React, { Component } from "react";

class Counter extends Component {
    render() {
        return (
            <div>
                <div>Counter</div>
                <button>Increment</button>
            </div>
        );
    }
}

export default Counter;

index.js

import React from "react";
import ReactDOM from "react-dom";
import Counter from "./components/counter";

ReactDOM.render(<Counter />, document.getElementById("root"));

State

setState is used for updating the state AND re-rendering the view i.e. syncing the DOM with the virtual DOM.

The method takes an object, and merges or overwrites the state object with it.

If we update the state directly, React is unaware of the change, and nothing is rendered.

Events

The event naming convention is to prefix the function with handle.

class Foo extends Component {
    handleSomething() {
        console.log("Something handled");
    }

    render() {
        return <button onClick={this.handleSomething}>Do something</button>;
    }
}

Binding this

onClick={this.handleSomething} results in undefined, because this references the global object and React runs in strict mode.

Arrow function

class Foo extends Component {
    state = {
        bar: "bar"
    };

    handleSomething = () => {
        console.log(this.state.bar);
    };

    render() {
        return <button onClick={this.handleSomething}>Do something</button>;
    }
}

bind()

Since we cannot use onClick={this.handleSomething("value")}, we need to use an arrow function.

class Foo extends Component {
    state = {
        bar: "bar"
    };

    handleSomething() {
        console.log(this.state.bar);
    }

    render() {
        return (
            <button onClick={this.handleSomething.bind(this)}>
                Do something
            </button>
        );
    }
}

Event arguments

class Foo extends Component {
    state = {
        bar: "bar"
    };

    handleSomething = argument => {
        console.log(argument);
    };

    render() {
        return (
            <button onClick={() => this.handleSomething("baz")}>
                Do something
            </button>
        );
    }
}

CSS

class Foo extends Component {
    styles = {
        fontSize: 10,
        fontWeight: "bold"
    };

    render() {
        return <div style={this.style}>Some text</div>;
    }
}
class Foo extends Component {
    render() {
        return (
            <div style={{ fontSize: 30, fontWeight: "bold" }}>Some text</div>
        );
    }
}