React Beyond Basics
React Fundamentals

All the React Fundamentals in One Place

I jammed all the basic theory that you need to learn about React in this one single article to get it all out of the way. All the code examples I wrote here are purely intended to provide examples of concepts. Most of them can be written in better ways.

Read this article carefully and try to understand every single concept it explains. However, not all concepts will sink in from the very first read. This is normal. Abstract examples are not the best, but before you can write fun practical examples you need to be introduced to these theoretical concepts.

I designed the article to be a reference for you to come back to when you need to brush up on some concept while building the fun games. When a concept I use while building these games challenges you, you can come back to this article to refresh your memory about that concept.

To follow along with all the examples that we will do from now on, you can use the jsComplete Playground (jscomplete.com/playground). It is a tool where you can test your JavaScript and React code right in the browser without any need to install or configure anything.

picture5

The tool has a simple 2-panel interface. The left panel is the editor where you write your JavaScript and React code. The latest version of both React and ReactDOM are already pre-loaded there. The editor also understands the JSX extension and all the modern features in JavaScript. This will allow you to focus on the React API itself rather than configuring and compiling a React application.

The right panel is the preview panel. You have a pre-defined mountNode DOM element in the editor. When you execute your JavaScript code, anything you put in the mountNode element shows up in the preview panel. The preview panel will also show any errors you encounter when you execute your code. The playground is also a simple JavaScript REPL (Run, Eval, Print, Loop) where you can test quick JavaScript functions and expressions. To execute the code at any time, press CTRL+Enter.

Try the following in the line, for example:

mountNode.innerHTML = 'Hello!!';

Or use the simple REPL mode:

3 == '3'

Let’s now dive right into the core concepts about React. Starting with the most important one: The Component.

React is All About Components

React is designed around the concept of reusable components. You define small components and then you put them together to form bigger components. All components small or big are reusable, even across different projects.

A React component—in its simplest form—is a plain-old JavaScript function:

// Example 2.1 - Creating components using functions
// jsdrops.com/rg-2.1

function Button (props) {
  // Returns a DOM element here. For example:
  return <button type="submit">{props.label}</button>;
}

// To render a Button element in the browser
ReactDOM.render(<Button label="Save" />, mountNode);

Note how I wrote what looks like HTML in the returned output of the Button function above. This is neither JavaScript nor HTML, and it is not even React. However, it is so popular that it became the default in React applications. It is called JSX and it is a JavaScript extension. JSX is also a compromise! We will talk about JSX in the next section.

Go ahead and try to return any other HTML element inside the Button function above and see how they are all supported (for example, return an input element or a textarea element).

The ReactDOM.render call on the last line is what you need to do to render a DOM element represented by the Button component in the browser.

The first argument of the ReactDOM.render method is what to render (a Button React element) and its second argument is the destination DOM node, which React is going to take over and control. This destination DOM node has to be statically pre-rendered in the HTML we load from a web server. The special mountNode jsComplete playground variable is a reference to a server-rendered HTML element in the preview panel. You can actually replace it with document.getElementById('mountNode').

Note how a React component name starts with a capital letter. This is required since we will be dealing with a mix of DOM elements and React elements. Lowercase names are reserved for HTML elements. In fact, go ahead and try naming the React component “button” instead of “Button” and see how ReactDOM will totally ignore the function and render a regular empty HTML button.

// Wrong:

const button = () => (
  // JSX
);

A React element can receive a list of attributes when it gets rendered, just like HTML elements. The Button element above received a label attribute. In React, the list of attributes received by a React element is known as props. A React function component receives this list as its first argument.

When using a function component, you don’t have to name the list of attributes as props, but that is the standard practice. When using class components, which we will do below, the same list of attributes is always presented with a special instance property named props.

You can Create Components Using Classes

Simple function components are great for presenting UI elements. Interacting with elements usually requires more features than what a function component can offer. React supports creating components through the JavaScript class syntax as well. Here is the same Button component written with the class syntax:

// Example 2.2 - Creating components using classes
// jsdrops.com/rg-2.2

class Button extends React.Component {

  render() {
    // Returns a DOM element here. For example:
    return <button>{this.props.label}</button>;
  }

}

// Use it (same syntax)
ReactDOM.render(<Button label="Save" />, mountNode);
Throughout this book, when I make changes to code within related examples, those changes will be highlighted in bold. I also sometimes highlight important parts of the code that I would like to draw your attention to.

Using the class syntax is simple. You define a class that extends React.Component, which is one of the main classes in the React top-level API. It is one of a total of about 25 objects in that level. When I said the React API is small, I was not joking.

Your class-based React component has to at least define an instance method named render. This render method returns the element or list of elements that represent the output of an object instantiated from the component. Every time we use the Button class-based component above (for example, by rendering a <`Button` …​ />), React will instantiate an object from this class-based component and use that object’s representation to create a DOM element.

This is the reason why we used this.props.label inside the JSX in the rendered output above. Every component gets a special instance property called props that holds all values passed to that component’s element when it was instantiated. Unlike function components, the render function in class-based components does not receive any arguments.

Component, Element, or Instance?

Here’s a trick question: What does ReactDOM render in the browser, a component or an element?

Technically speaking, ReactDOM does not render a React component or a React element in the DOM. It renders DOM elements backed by instances of their components. This is true for class components. For function components, ReactDOM renders just DOM elements. Function components do not have instances (that can be accessed with this), so when using a function component, ReactDOM renders a DOM element generated from the function’s returned element.

What you need to understand here is that a React element is different from a DOM element. A React element is just a description of an HTML element (or a mix of HTML elements and other React elements).

A better question here might be: When you use something like <MyComponent /> in JSX, is that a component, an element, or an instance?

It’s an element, but not a DOM element. It’s a React element. The clue here is that any JSX tag gets translated to a React.createElement call. Keep that in mind.

We will see how JSX tags get translated to React elements in the next section.

However, for React to continue working with any React element, it will have to either invoke a function or create an instance from a class.

You might find the words component, element, and instance mixed up in the React guides and tutorials out there. I am guilty of mixing these words myself, but I think a React learner needs to understand the important distinctions.

Here is how I would explain the difference:

  • A React Component is a template. A blueprint. A global definition. This can be either a function or a class (with a render function).

  • A React Element is what gets returned from components. It’s an object that virtually describes the DOM nodes that a component represents. With a function component, this element is the object that the function returns and with a class component the element is the object that the component’s render method returns. React elements are not what you see in the browser. They are just objects in memory and you can’t change anything about them.

  • React internally creates, updates, and destroys instances to figure out the DOM elements tree that needs to be rendered to the browser. When working with class components, it’s common to refer to their browser-rendered DOM elements as component instances. You can render many instances of the same component. The instance is the “this” keyword that you use inside class-based components. You would not need to create an instance from a class manually. You just need to remember that it’s there somewhere in React’s memory.

  • Function-based React elements do not have instances. A function component can still be rendered multiple times but React just does not associate a local instance with each render. It just uses the invocation of the function to determine what DOM element to render for that function.

ReactDOM does not render components in the browser and it does not render elements either (in the sense of keeping the term element to represent the result of React.createElement). It also does not render instances. It renders DOM elements.

It is a common practice out there to use the word component to mean the template and the DOM element rendered based on it. The word component is a synonym to the word element after all.

In this book, I use the terms component class and component function when talking about templates and I use the terms React element, DOM element, and component instance to minimize the confusion.

The Story of a React Element

Every React App starts with a render call that uses a React element. Let’s go through the process with a simple example:

const Today = () => (
  <div>Today is {new Date().toDateString()}</div>
);

class HelloMessage extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div>Hello {this.props.name}</div>
        <Today />
      </React.Fragment>
    );
  }
}

ReactDOM.render(
  <HelloMessage name="Taylor" />,
  mountNode
);
React.Fragment is a recent feature in React. If you need the component to return multiple elements without having to wrap them in an extra DOM element, you can do that with React.Fragment or the new JSX empty tag (<></>) that gets compiled to React.Fragment.

The first React element is the one we start with in the ReactDOM.render call:

<HelloMessage name="Taylor" /> // This is a React element

This React element describes that the DOM tree to be rendered should start with the HelloMessage component class and a name prop value that’s equal to Taylor.

React now needs to answer the question: What is HelloMessage?

Every time a React element describes a React component class or component function, React uses the component to replace the description with what the component returns. It creates an instance for class-based components at this point and keeps a reference of that in memory. It does not create anything for function-based components; it just invokes them.

What gets returned from the HelloMessage component class render method is a new React element that describes a React.Fragment component.

React now needs to answer the question: What is React.Fragment?

React will keep reducing these unknown descriptions of components until it has only valid DOM nodes. The description of React.Fragment gets translated into two React elements, one describing a div and another describing a Today component.

React now needs to answer the question: What is Today?

It calls the Today component function to figure this last question out. The Today function returns a React element that describes a div.

At this point, the virtual tree is complete with all React elements that describe DOM nodes. React uses its reconciliation algorithm to figure out what to update in the browser. The nodes that were translated with a component instance retain the power of modifying that instance.

JSX is a JavaScript Extension

Example 2.1 can be written in pure React without JSX as follows:

// Example 2.3 - React component without JSX
// jsdrops.com/rg-2.3

function Button (props) {
  return React.createElement(
    "button",
    { type: "submit" },
    props.label
  );
}

// To render a Button element
// you would do something like
ReactDOM.render(
  React.createElement(Button, { label: "Save" }),
  mountNode
);

The React.createElement function is another main function in the React top-level API that you need to learn. Much like the DOM itself having a document.createElement function to create a DOM element specified by a tag name, the React.createElement function can be used to describe a DOM element specified by a tag name (first use above). React.createElement can also be used to describe a React component (second use above).

However, unlike document.createElement, React.createElement accepts a dynamic number of arguments after the second one to represent the children of the element to be created. So React.createElement actually creates a React element to represent a tree.

Here is an example of that:

// Example 2.4 -  The React.createElement API
// jsdrops.com/rg-2.4

const InputForm = React.createElement(
  "form",
  {target:"_blank", action:"https://google.com/search"},
  React.createElement(
    "div",
    null,
    "Enter input and click Search"
  ),
  React.createElement(
    "input",
    { name: "q", className: "input" }
  ),
  React.createElement(Button, { label: "Search" })
);

// InputForm uses the Button component
// so we need that too:
function Button (props) {
  return React.createElement(
    "button",
    { type: "submit" },
    props.label
  );
}

// Then we can use InputForm directly with .render
ReactDOM.render(InputForm, mountNode);

Note a few things about the example above:

  • InputForm is not a React component; it is just a React element. This is why we used it directly in the ReactDOM.render call and not with <InputForm />.

  • The React.createElement function accepted multiple arguments after the first two. Its list of arguments starting from the third one comprises the list of children for the created element.

  • We were able to nest React.createElement calls because they produce simple JavaScript objects that can be passed around in arguments.

  • The second argument to React.createElement can be null or an empty object when no attributes or props are needed for the React element.

  • React’s API tries to be as close to the DOM API as possible, which is why we use className instead of class for the input element.

I hope the DOM API in the future will be influenced by the React API. The DOM API is publicly hated by many. The React API is a much more developer-friendly API to work with.

The code in example 2.4 can be directly used in a browser after including the React and ReactDOM libraries. The browsers do not deal with any of the JSX business. However, we humans like to see and work with HTML instead of these createElement calls (imagine building a website with just document.createElement, which you can!). This is why the JSX compromise exists. Instead of writing the form above with React.createElement calls, we can write it with syntax very similar to HTML:

// Example 2.5 - JSX (compare with example 2.4)
// jsdrops.com/rg-2.5

const InputForm =
 <form target="_blank" action="https://google.com/search">
   <div>Enter input and click Search</div>
   <input name="q" className="input" />
   <Button label="Search" />
 </form>;

// InputForm "still" uses the Button component
// so we need that too.

// Either JSX or normal form would do
function Button (props) {
  // Returns a DOM element here. For example:
  return <button type="submit">{props.label}</button>;
}
// Then we can use InputForm directly with .render
ReactDOM.render(InputForm, mountNode);
Remember that what was highlighted in bold above is not HTML. This is a common misunderstanding in React. Keep in mind that this will always be translated into React.createElement calls. For clues about that, note how className was used instead of class and how a semicolon was added at the end.

The syntax of what is being returned from the functions in the example above is JSX, yet what we took to the browser is the compiled version of it (example 2.4). To use JSX in your source code, you need to use a preprocessor (like Babel) to convert the JSX version into the React.createElement version. The jsComplete playground has that built-in.

That is JSX. It is a compromise that allows us to write our React components in syntax similar to HTML, which is a pretty good deal.

JSX, by the way, can be used on its own. It is not a React-only thing.

You Can Use Expressions in JSX

Within any JSX opening and closing brackets, you can capture the result of any JavaScript expression using a pair of curly brackets.

// Example 2.6 - Using JavaScript expressions in JSX
// jsdrops.com/rg-2.6

const RandomValue = () =>
  <div>
    { Math.floor(Math.random() * 100) }
  </div>;

// To use it:
ReactDOM.render(<RandomValue />, mountNode);

Any JavaScript expression can go inside these curly brackets. This is equivalent to the ${} interpolation syntax in JavaScript template literals. This is the only constraint inside JSX: Only expressions. For example, you cannot use a regular if-statement, but a ternary expression is okay.

JavaScript variables are also expressions, so when the component receives a list of props you can use these props inside curly brackets. We did this in the Button component in Example 2.1. Receiving props is optional (the RandomValue component above did not receive any).

JavaScript objects are also expressions. Sometimes we use a JavaScript object inside curly brackets, which makes it look like double curly brackets, but it is really just an object inside curly brackets. One use case of that is to pass a CSS style object to the special style attribute in React:

// Example 2.7 - Object passed to the special style prop
// jsdrops.com/rg-2.7

const ErrorDisplay = ({message}) =>
  <div style={ *{ color:'red', backgroundColor:'yellow' } *}>
    {message}
  </div>;

// Use it:
ReactDOM.render(
  <ErrorDisplay
    message="These aren't the droids you're looking for"
  />,
  mountNode
);

Note how I destructured only the message out of the props argument. It is all JavaScript. Also note how the style attribute above is a special one. We use an object as the value of the style attribute. That object defines the styles as if we are doing so with JavaScript (because we are).

You can even use a React element inside JSX, because that too is an expression. Remember, a React element is just a function call:

// Example 2.8 - Using a React element within {}
// jsdrops.com/rg-2.8

const MaybeError = ({errorMessage}) =>
  <div>
    {
      errorMessage &&
      <ErrorDisplay message={errorMessage} />
    }
 </div>;

// The MaybeError component uses
// the ErrorDisplay component:

const ErrorDisplay = ({message}) =>
  <div style={ {color:'red', backgroundColor:'yellow'} }>
    {message}
  </div>;

// Now we can use the MaybeError component:

ReactDOM.render(
  <MaybeError
    errorMessage={Math.random() > 0.5 ? 'Not good' : ''}
  />,
  mountNode
);

The MaybeError component above would only display the ErrorDisplay component if there is an errorMessage string passed to it. Otherwise, it will display an empty div. React considers {true}, {false}, {undefined}, and {null} to be valid nodes that do not render anything.

You can also use all of JavaScript functional methods on collections (map, reduce, filter, concat, and so on) inside JSX because they all return expressions:

// Example 2.9 - Using an array map inside {}
// jsdrops.com/rg-2.9

const Doubler = ({value=[1, 2, 3]}) =>
  <div>
    {value.map(e => e * 2)}
  </div>;

// Use it
ReactDOM.render(<Doubler />, mountNode);

Note how I gave the value prop a default value above (it’s just a regular JavaScript argument-destructured property). Note also how I outputted an array expression inside the div. React allows using arrays in expression. When ReactDOM needs to render that, it will place every doubled value in that array in a text node. More on that later.

You Can Customize a Component Instance

When working with class components, remember that each time you render an element from that component the element will have its own backing instance. You can define anything you wish on that instance. For example, you can customize the instance after it gets constructed using the regular JavaScript constructor function that will be invoked for each instance:

// Example 2.10 - Customizing a component instance
// jsdrops.com/rg-2.10

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.id = Date.now();
  }

  render() {
    return (
      <button id={this.id}>{this.props.label}</button>
    );
  }
}

// Use it
ReactDOM.render(<Button label="Save" />, mountNode);

You can also define class-field functions and use them anywhere you wish, including inside the returned JSX output:

// Example 2.11 — Using class properties
// jsdrops.com/rg-2.11

class Button extends React.Component {
  clickCounter = 0;

  handleClick = () =>
    console.log(`Clicked: ${++this.clickCounter}`);

  render() {
    return (
      <button id={this.id} onClick={this.handleClick}>
        {this.props.label}
      </button>
    );
  }
}

// Use it
ReactDOM.render(<Button label="Save" />, mountNode);

Note a few things about Example 2.11 above:

  • The handleClick function is written using the new proposed class-field syntax in JavaScript. This is still at stage-3, but it is a good option to access the component mounted instance (thanks to arrow functions). However, you need to use a compiler like Babel configured to understand stage-3 (or just the class-field syntax) to get the code above to work. The jsComplete playground has this syntax pre-configured.

  • I also defined the clickCounter instance variables using the same class-field syntax. This allowed me to skip using a class constructor call altogether.

  • When I specified the handleClick function as the value of the special onClick React prop, I did not call it. I passed in the reference to the handleClick function. Calling the function on that level is one of the most common mistakes when working with React.

// Wrong:
onClick={this.handleClick()}

// Right:
onClick={this.handleClick}

React Optimizes Event Handlers

When handling events inside React elements, there are two important differences from the way we do so with the DOM API:

  • All React elements attributes (events included) are named using camelCase, rather than lowercase. It is onClick, not onclick.

  • You pass an actual JavaScript function reference as the event handler, rather than a string. It is onClick={handleClick}, not onClick="handleClick". React wraps the native DOM event object with an object of its own, which is known as a ynthetic event. It uses this wrapper to optimize the performance of native events handling. But inside an event handler, you can still access all methods available on the native DOM event object. React passes that wrapped event object to every handle call. For example, to prevent a form from the default submission action, you can do:

// Example 2.12 - Working with wrapped events
// jsdrops.com/rg-2.12

class Form extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault();
    console.log('Form submitted');
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <button type="submit">Submit</button>
      </form>
    );
  }
}

// Use it
ReactDOM.render(<Form />, mountNode);
Not everything you can do inside a regular native DOM event handler can be done inside a React event handler. For example, you can’t return false to prevent the default behavior of the event. The React event object is also special in the fact that it cannot be used asynchronously. For example, you can’t access it within a timer function.

Every React Component Has a Story (Part 1)

The following applies to the class component only (those that extend React.Component). Function components have a slightly different story.

  • First, we define a template for React to create elements from the component.

  • Then, we instruct React to use it somewhere. For example, inside a render call of another component, or with ReactDOM.render.

  • Then, React instantiates an element and gives it a set of props that we can access using this.props. Those props are exactly what we passed in the instantiation step above.

  • Since it is all JavaScript, the constructor method will be called (if defined). This is the first method of what is known as component lifecycle methods.

  • React then computes the output of the render method (the React element that virtually describes a DOM element). Remember that if the React element describes another React component, React will repeat the steps above until it has a description of just DOM elements.

  • Since this is the first time React is rendering the DOM element, React will communicate with the browser (on our behalf, using the DOM API) to display the DOM element there. This process is commonly known as mounting.

  • Once the DOM element is mounted in the browser’s DOM, React invokes another lifecycle method on the component instance: componentDidMount. For example, we can use this method to do something on the DOM element that we now know exists in the browser. Prior to this lifecycle method, the DOM we worked with was all virtual (from React elements).

  • Some components' stories end here. Other components get unmounted from the browser DOM for various reasons. Right before the latter happens, React invokes another lifecycle method on the component instance: componentWillUnmount.

  • The state associated with the instance of any mounted DOM element might change and the parent of that component might get re-rendered. In either case, the React element representing the DOM element might receive a different set of props. React magic happens here and we actually start needing React at this point! Honestly, prior to this point, we did not need React at all.

The story of this component continues, but before it does, we need to understand this "state" thing that I speak of.

React Components Can Have Private State

The state property is a special one in any React component. React monitors every component’s state for changes, but for React to do so efficiently, we have to change the state property through another React API method: setState for class components, and useState for function components.

Here is an example use of setState:

// Example 2.13 -  the setState API
// jsdrops.com/rg-2.13

class CounterButton extends React.Component {
  state = {
    clickCounter: 0,
    currentTimestamp: new Date(),
  };
  handleClick = () =>
    this.setState(prevState => ({
      clickCounter: prevState.clickCounter + 1
    }));
  componentDidMount() {
    setInterval(() => {
      this.setState({ currentTimestamp: new Date() });
    }, 1000);
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click</button>
        <p>Clicked: {this.state.clickCounter}</p>
        <p>
          Time: {this.state.currentTimestamp.toLocaleString()}
        </p>
      </div>
    );
  }
}

// Use it
ReactDOM.render(<CounterButton />, mountNode);

This is probably the most important example to understand in this article. It will basically complete your fundamental knowledge of the React way. After this example, there are a few other small things that you need to learn, but it is mostly you and your JavaScript skills from that point.

Let’s walk through Example 2.13, starting with the two class fields. The special state field is initialized with an object that holds a clickCounter that starts with 0 and a currentTimestamp that starts with new Date().

Note how I did not need a constructor function to initialize the state object thanks to JavaScript class-fields. More details on this later.

The second class field is a handleClick function, which we passed to the onClick event for the button element inside the render method. The handleClick method modifies this component instance state using setState. Take notice of that.

The other place we are modifying the state is inside an interval timer that we started inside the componentDidMount lifecycle method. It ticks every second and executes another call to this.setState.

In the render method, we used the two properties we have on the state with a normal read syntax. There is no special API for reading the state object.

Now, notice that we updated the component instance state using two different contracts for setState:

  • Passing a function that returned an object. We did that inside the handleClick function. This function is known as the updater function.

  • Passing a regular object. We did that inside the interval callback.

Both ways are acceptable, but the first one is preferred when you read and write to the state at the same time (which we do). Inside the interval callback, we are only writing to the state and not reading it.

How do we update the state? We use an object with the new value of what we want to update. Notice how in both calls to setState, we are only using one property from the state field and not both. This is completely okay because setState actually merges the object that it receives (or the object its updater function returns) with the existing state. So, not specifying a property while calling setState means that we wish to not change that property (but not delete it).

Most of the React API methods have verbose names. I just wish they named setState with what it actually does: scheduleShallowMergeWithState

React Will React

React gets its name from the fact that it reacts to component state changes (although not reactively, but on a schedule). I read a joke somewhere that React should have been named Schedule!

However, what we witness with the naked eye when the state of any component gets updated is that React reacts to that update and automatically reflects the update in the browser DOM (if needed).

Think of the render function’s input as both:

  • The props that get passed by the parent.

  • The internal private state that can get updated anytime.

When the input of the render function changes, its output might change.

React keeps a record of the history of renders and when it sees that one render is different than the previous one, it will compute the difference between them and efficiently translate it into actual DOM operations that get executed in the DOM.

You can think of React as the agent we hired to communicate with the browser. Take the current timestamp display (in 2.13 above) as an example. Instead of manually going to the browser and invoking some DOM API operations to find and update the p#timestamp DOM element every second, we just changed a property on the state of the component instance and React did its job of communicating with the browser on our behalf. I believe this is the true reason why React is popular. We hate talking to Mr. Browser (and the so many dialects of the DOM language that it speaks) and React volunteered to do all the talking for us, for free.

We mostly need to communicate with just React, our agent, and not the browser itself. I say mostly because there are cases where we still need to communicate with the browser, but those are rare.

Every React Component Has a Story (Part 2)

Now that we know about the state of a component and how when that state changes some magic happens, let’s learn the last few concepts about that process.

  • A component might need to re-render when its state gets updated or when its parent decides to change the props that it passes to the component

  • If the latter happens, React invokes another lifecycle method on the component instance: componentWillReceiveProps.

  • If either the state object or the passed-in props object is changed, React has an important decision to make. Should the DOM element represented by the component be updated? This is why it invokes another important lifecycle method on the component instance at this point: shouldComponentUpdate. This method is an actual question, so if you need to customize or optimize the render process on your own, you have to answer that question by returning either true or false.

  • If there is no custom shouldComponentUpdate method specified, React defaults to the very smart diffing process that it is famous for and that process is good enough in most situations.

  • React invokes another lifecycle method on the instance at this point: componentWillUpdate. Then, React computes the new rendered output and compares it with the last rendered output.

  • If the rendered output is exactly the same, React does nothing (no need to talk to Mr. Browser). If there is a difference, React takes that difference to the browser as we’ve seen before.

  • In any case, since the React update process happened anyway (even if the output was exactly the same), React invokes the final lifecycle method on the component instance: componentDidUpdate.

Lifecycle methods are essentially escape hatches. If you are not doing anything special, you can create full applications without them. They are very handy for analyzing what is going on in the application and for further optimizing the performance of React updates.

That’s it. Believe it or not, with what you learned above (or parts of it, really), you can start creating some interesting React applications.