React
Academy

React Cheatsheet


Components in React

  • This is how components works in React
  • Data drives the UI
  • To change the UI, we must first update the data
  • No two-way binding. Only one-way binding
React Cycle

How to update components

  • This is how React updates components, in more details
React Cycle

Think in React

  • Decompose the UI into components
    • Each component will render itself, based on external and internal data
    • Build trees of the components to create app
Todos App

Describe the result

  • React tries to be declarative instead of imperative
    • Don't try to modify the display (imperative) (like in jQuery)
    • Instead, just describe the result
      • React will figure out the changes that need to happen in DOM
<!-- let's describe the following -->
<h3 title="alarm">The alarm goes off at 10:04 AM</h3>

Create components

  • Components are functions (or classes)
    • Always start with an uppercase letter
    • Take a single argument called props
  • Components return (or render) a 'React element' (also called 'virtual element')
//Simple Component.
//Starts with uppercase
//takes a single argument
function SimpleComponent(props) {
  return null;
}

JSX to the rescue

  • React Elements should be created by JSX
  • JSX is an easy syntax to create React elements
    • looks like HTML (gets transpiled by the Babel transpiler to regular JS)
    • Inside of JSX, curly braces switches to JS

// This is the code to display the time ⮯⮯.
function DisplayAlarm(props) {
  return (
    // JSX is often enclosed in round brackets ()
    <h3 title='alarm'>The alarm goes off at {props.alarmTime}</h3> 
    //      curly braces {} switches to JS ⮭⮭
  );
}
//Babel converts JSX to either to _jsx() ot React.createElement() ⮭⮭

JSX gets converted to Regular JS

  • Browsers don't know how to deal with the JSX.
  • JSX is converted to _jsx() by the Babel transpiler.
  • _jsx() is internal, called by Babel. But you can achieve a similar effect using React.createElement()

//JSX gets transpiled to the following JS
function DisplayAlarm(props) {
  return _jsx(
    'h3',
    { title: 'alarm', 
      children: ['The alarm goes off at ', props.alarmTime], 
    },
   
  );
}

How React works behind the curtain

  • JSX and _jsx() are going to generate React elements.
    • React elements will describe a Virtual DOM (vDom)
    • Virtual DOM works quicker than the DOM, because React Elements are simple JS objects.
  • React has a 'reconciliation' phase
    • Called after a component (and all its children) are generated
      • The elements are generated to the virtual Dom (or vDom):
      • React compares current elements with the previous elements of the vDom
      • Any modification will generate the smallest DOM change possible
//This is what the JSX converted to the
//raw React elements looks like
function DisplayAlarm(props) {
  return {
    type: 'h3',
    props: {
      title: 'alarm',
      children: ['The alarm goes off at ', props.alarmTime],
    },
    key: null,
    ref: null,
    $$typeof: Symbol.for('react.element'),
  };
}

Components create a tree

  • You can use components from other components.
  • You build a "component tree" to describe your app
function DoubleAlarmClocks(props) {
  return (
    <div>
      {/* call other components */}
      <DisplayAlarm alarmTime={props.time1} />
      {/* multiple times */}
      <DisplayAlarm alarmTime={props.time2} />
    </div>
  );
}
//all tags in jsx must be closed, or self-closed ⮭⮭

Use props to push data down

  • Data coming from a parent component is called "props" (properties)
  • Props are pushed from parent to children through JSX attributes
  • Props are passed as the argument to the function.
  • Props are "destructured" using the destructuring assignment {}
//We are "destructuring" the props parameter ⮯⮯
function DoubleAlarmClock({time1, time2}) {
  return (
    <div>
      <DisplayAlarm alarmTime={time1} />    
      <DisplayAlarm alarmTime={time2} />
    </div>
  );
}

Store data in State

  • Modifiable data in React is called "state".
  • State is defined by the useState function.
  • Initial values are used the first time we run the compponent (Mount)
  • useState returns an array composed of two items
    • First item is the data value (state)
    • Second is a function to change that data (setState).
  • NEVER change the state directly
    • Intead, use the setState function
    • This will schedule a rerender of the component (and child components)
import { useState } from 'react';
//named export ⮭⮭

function Counter({name}) {
  const [counter, setCounter] = useState(5);
  //set to 5 the first time it's called ⮭⮭
  //use counter to read the data
  //use setCounter to write the data

  //here is function inside a function
  //called by the click event ⮯⮯
  function increment(evt) {
    setCounter(counter + 1);
  }

  return (
    <div>
      <h1>
        Hello {name}, the count is: {counter}
      </h1>
      <button onClick={increment}>Add 1</button>
    </div>
  );
}
// events are wired this way in React: onClick={fn} ⮭⮭
// It is a synthetic event, different than
// a real DOM event: onclick="increment".
// (Notice the difference in casing)
// Use synthetic events whenever possible.

Change the state to rerender

  • When state (or props) change, or the parent re-renders, your component updates AUTOMATICALLY.
  • You never have to modify the DOM yourself
    • If you ever do, then you're not using the proper React way
function Counter({name}) {
  const [counter, setCounter] = React.useState(5);

  function increment(evt) {
    setCounter(counter + 1);
  }
  //setCounter ⮭⮭ doesn't change the state right away
  //it schedules the change for right after the firing
  //of all events. Once all scheduled changes are done
  //changing the states, those component will now
  //"rerender" (along with the child components).

  return (
    <div>
      <h1>
        Hello {name}, the count is: {counter}
      </h1>
      <button onClick={increment}>Add 1</button>
    </div>
  );
}

Looping over items

  • Loop over an array of data with .map()
  • It returns an element for each iteration
  • For performance reasons, remember to provide an unique key for each element
const authors = [
  { id: 1, name: 'Jeff' },
  { id: 2, name: 'Bill' },
  { id: 3, name: 'Mary' },
];

function App() {
  return <AuthorList authors={authors} />;
}
function AuthorList({authors}) {
  return (
    <ul>
      {
        authors.map((author) => {
          return <li key={author.id}>{author.name}</li>;
        }) 
        //keys ⮭⮭ are used by React for performance
        //in reconciliation phase, not part of the DOM
      }
    </ul>
  );
}

Different ways to style

  • use CSS files and then set attribute with className='danger'
    • use 'className' ('class' is a reserved keyword in js)
  • Set inline styles with style={{backgroundColor: 'red' }}
  • Alternative, you could refer to a global style variable
    • const dangerStyle={backgroundColor: red}
<p className="danger">Text</p>
<p style={dangerStyle}>Text</p>
<p style={{backgroundColor: 'red', width: '300px', height: 300}}>
<!-- {/*  numeric values will be converted to 'px' units */} -->

Use a third-party library for theming and styling

Here is a list of libraries to help you generate css from js.

  • Aphrodite
  • Emotion
  • Glamor
  • Fela
  • Styletron
  • Jss
  • Radium
  • React-Native-Web
  • Styled-Component
  • CSS-in-JS (Facebook 2019?)

Use effect

  • First argument of useEffect() takes a function.
    • Runs right after reconciliation and painting the screen.
    • Inside of this callback, you perform async functions and side effects
      • Manipulating the DOM (read or write) is a side effect
      • Network calls are async functions
  • The second argument is a "change array" of dependencies
    • Effect gets called only when an item in the array is modified
      • Code should include in array any var that might change.
    • Put null or nothing to execute after all renders
    • Put an empty array [] for the effect to be called just once, right after the first render (when React "mounts" the component)

Code sample of useEffect

import { useState, useEffect } from 'react';
const url = 'https://randomuser.me/api/';

function DisplayUser({id});

  useEffect(() => {
    fetch(`${url}?seed=${id}`)
      .then((response) => response.json())
      .then((data) => setData(data.results[0]));
  }, [id]);
  // useEffect ⮭⮭ is called after each render
  // where id was modified (by the parent component)

  //we return the render result ⮯⮯
  return (
    <div>
      {data ? ( // if no data, show a "no data" msg
        <p>
          <img src={data.picture.thumbnail} />
          {data.name.first}
        </p>
      ) : (
        <p>No data (yet)!</p>
      )}
    </boxed>
  );
}

Returned effect: Cleanup

  • The returned function is cleanup. it is called either:
    • Just before the next effect is called, but after React rendered
    • Just after the component is destroyed (when react "unmounts" the component)
  • Makes it easy to subscribe and unsubscribe to stuff
useEffect(() => {
  chatSubscribe(friendId);
  return function cleanup() {
    chatUnsubscribe(friendId);
  };
}, [friendId]);
//Each time the chat is re-rendered, if friendId was
//modified, then we unsubscribe to the previous chat,
//just before subscribing to the new friendId. The magic
//of "closures" will ensure the old friendID gets
//unsubscribed, not the current one.

React Academy

To get the latest version of this document, visit the handout section of ReactAcademy.live.