React

A web UI library.

import React from 'react';
import ReactDOM from 'react-dom';
let e = React.createElement(type, props, children..)
// e is plain JS object, not a DOM object
// props is an object with DOM properties for type's attributes
e.props.children[i]


{
  type: 'a',
  props: {
    href: 'https://xkcd.com/221/',
    children: {
      type: 'img',
      props: {
        src: "https://imgs.xkcd.com/comics/random_number.png",
        alt: "RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.",
      }
    },
  },
}

const square = createElement(
  'div',
  {
    // The `style` prop accepts an object of styles
    style: {
      width: '100px',
      height: '100px',
      backgroundColor: 'red',
      margin: '10px',
    }
  }
)

const container = createElement(
  'div',
  {
    // The `className` prop set's the element's CSS class.
    // The `blue-border` class is defined in styles.css.
    className: 'blue-border', 
  },

  // The remaining arguments list the element's children
  square,
  square
)

ReactDOM.render(
  container,
  document.getElementById('root')
)

Props need to be named after DOM properties - not HTML attributes.

JSX

JS XML. JSX expressions are just normal JS objects.

let element =
  <div className='test'>
    Hello, world!
  </div>

let element =
  React.createElement(
    'div',
    { className: 'test' },
    "Hello, world!"
  )

Rules

  1. <tags> are elements JSX <tags> map to calls to React.createElement().
let element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
  1. JSX children become child elements The children of a JSX tag map to the third and subsequent arguments of React.createElement(), i.e. they become the element’s props.children. JSX children can be text, elements, or a mix of both.

  2. JSX attributes become props

  1. {} interpolates children When a pair of {} braces is encountered within a JSX element, it’s value will be interpolated in.
let w = "World"
let hellos = <div>Hello, {w}</div>

Components

import React, { Component } from 'react';

export default class XYZ extends Component {
  // optional
  state = {
    name: "x",
    value: this.props.param
  };
  render() {
    return <p>hi {this.state.name} {this.state.param}</p>;
  }
}

Can use it elsewhere using e.g., <XYZ key={x.id} param={8}/>, where param is any parameter you want to use. Can use multiple attributes, which can all be accessed using props. To pass child react objects, use e.g., <XYZ> <p> ... </p> </XYZ>. Accessed by the component using this.props.children. Note that props is read-only. Since state is private to the component, it should only be modified/removed by that component. State should be lifted up to parent components if they need to be aware of child state; other controlling components might also need to handle the state.

To return multiple elements:

return (
  <div>
    {this.props.children}
    <p>hi</p>
    <p>bye</p>
  </div>
  )

The div can be avoided using React.Fragment which then won’t appear in the DOM.

Rendering

// Lists

let xs = ["1", "2", "3"];

// a unique key is necessary for react to track the element. e.g. object.id
let jsx = <ul> xs.map(x => <li key={x}>{x}</li>) </ul>;

// Conditional
// usual if-else or
let s = <div className={this.getBadge()}></div>
let b = <button onClick={this.handleClick}></button>

handleClick() {
  // no access to 'this'
  // need below in the class ctor
  // this.handleClick = this.handleClick.bind(this);
}

handleClick = () => {
  // has access to 'this'
  this.setState({ count: this.state.count + 1});
}

Raising and handling events

Useful for removing components.

class Counters extends Component {
  state = { counters: [ ... ]};

  handleDelete = ctrId => { ... };

  render() {
    return ... <Counter onDelete={this.handleDelete} ... />
  }
}


class Counter extends Component {
  render() {
    <button onClick={() => this.props.onDelete(this.props.id)} />
  }
}

Lifting State

Controlled component

Has no local state; receives all data from parent. Raises events to communicate with parent.

Stateless Functional Components

Can avoid the class when no state.

const NavBar = (props) => {
  return ( ... props.x ... )
}

// or better, using object destructuring {}
const NavBar = ({x}) => {
  return ( ... x ... )
}

Component Lifecycle

Note the ordering below matters. The functions are hooks.

When a change occurs, React keeps both the old and new vDOMs in place. Render affects the whole vDOM (from that node onwards?), but only the diffs are applied to the DOM.

Unmount is used for clean-ups (timeouts, etc).

Folder structure

References

https://frontarm.com/courses/react-fundamentals https://www.youtube.com/watch?v=Ke90Tje7VS0 React JS - React Tutorial for Beginners