React: Foundation — Basics

React Basics

Learning outcomes:

  • What are React nodes
  • What are React elements and how to create them using JSX
  • What are props in React
  • Working with events
  • What are components and how to create them
  • Working with state using useState()

Introduction

So far uptil now in this course, we've gone through a decent amount of concepts in React, including what exactly is React, how to set up its development environment, creating our very first React program, and so on.

Still, though, we haven't understood how all the machinery comes together and that precisely what are the bits and pieces that make up a React application, for e.g. React nodes, elements, props, components, and much more.

In this chapter, we shall build the foundational knowledge by exploring these fundamental ideas of React and thus prepare ourselves for the subsequent part of this course, where we'll be digging deeper into each idea.

What are React nodes?

At the core, all React applications are made up of these bits and pieces known as React nodes (elements, textual pieces, and so on).

The official documentation of React doesn't formally define or use the phrase 'React nodes.' I use it for two reasons:

  1. Type declarations in the React library label the third parameter of React.createElement() as a rest parameter, each of whose arguments implements the ReactNode type (if you've worked with TypeScript before, you'll be able to understand what this means). Notice the name ReactNode.
  2. Using the term 'React node' simplifies the discussion when I want to talk about React.createElement() or anything to be rendered by React.

So what exactly do I mean by a React node?

Well, React nodes can be any of the following: React elements, strings, Booleans, numbers, undefined, null, and arrays of React elements.

Any other value besides the ones listed above doesn't constitute a React node and thus couldn't be used wherever React expects a React node.

How exactly each of these values is handled by React will be explored later on as this course proceeds. For now, let's concern ourselves with the most important kind of React nodes — React elements.

What are React elements?

React elements are described as follows by React's documentation, specifically in Glossary of React Terms:

React elements are the building blocks of React applications.

There's absolutely no doubt in this.

When we build UIs on the web, we always require HTML elements such as <div>, <section>, <header>, <footer>, <p>, <h1>, <img>s, and so on and so forth. We just can't build literally anything without these core pieces.

In JavaScript, we create these HTML elements by constructing HTML DOM elements.

React adds an abstraction layer on top of these DOM elements, calling them as React elements. So in that way, we might say that React elements are abstractions over DOM elements.

For instance, when we are working in React, the <h1>React element is not the same thing as an <h1> HTML DOM element.

Obviously, a React <h1> element probably references an HTML DOM <h1> element internally, but it also includes a host of other React-specific utilities which drive the ideology of React.

However, this isn't the only purpose of React elements. As we shall learn later on, React elements are either abstractions over HTML DOM elements, or instances of components.

A component is another cornerstone idea of React (and many other frontend UI tools). We shall understand it in depth in the React Components chapter, but to get a quick overview of it, it can be thought of as a custom element.

So to precisely define it:

A React element is either an abstraction over an HTML DOM element or an instance of a component.

Either way, the notion of a React element is an extremely important one, that is used as early as creating our very first program in React.

The createElement() function

To create a React element, we use the createElement() function (exported by the react package).

createElement(type, props, ...children)
  • type specifies the type of the element to create. When it's a string, the created element abstracts an HTML DOM element. When it's a function, the created element represents a component instance (more on this later).
  • props is an object specifying the props of the element. For DOM elements, we use these props to set attributes on those elements.
  • children placeholds all the arguments starting from the third one and represents all the React nodes to put inside the created element as children.
createElement() creates a React element, NOT an HTML DOM element. The return value of createElement() is not an HTML DOM element which is otherwise returned by document.createElement().

Recall the following code from the React First Program chapter:

javascript
const element = React.createElement(
   'h1',
   { contentEditable: true },
   'Hello World!'
);

Here, we're essentially trying to achieve the following HTML:

HTML
<h1 contenteditable="true">Hello World!</h1>

Let's understand the arguments given to createElement() above:

  • 'h1' is used because we need to create an <h1> element (in React). Remember that strings correspond to DOM elements.
  • Because we need to set the contenteditable attribute on the <h1> element, we have the second argument as an object containing the contentEditable property, and that set to true. (Notice the uppercase 'E' in contentEditable — this is by virtue of the naming of the property in the DOM. We shall learn more about this in React Props.)
  • 'Hello World!' specifies the content to put inside the <h1>.

This wasn't that hard to understand, was it?

Let's consider a more complex example.

Say we want to achieve the following HTML:

HTML
<div>
   <h1>A heading</h1>
   <p>A paragraph</p>
</div>;

Here's how we'll do so using createElement():

javascript
createElement(
   'div',
   null,
   createElement('h1', null, 'A heading'), 
   createElement('p', null, 'A paragraph')
);

Here's what's going on here:

  • The main element is <div>, likewise the first arg to the main, outer createElement() call is 'div'.
  • No attributes are required on the <div> element, likewise the second arg is null.
  • The next two args are React elements themselves, i.e. an <h1>, followed by a <p>. They both are placed inside the <div> element being created.

Simple.

Now, although React's createElement() isn't imperative like the document.createElement() DOM method, it still is a bit tedious to work with.

You would almost never find big React apps — not even small apps really — developed by using such createElement() calls. Instead, you'll almost always find React elements created using JSX.

React elements in JSX

A JSX element resembles the syntax of constructing elements in HTML and is basically just syntactic sugar over createElement().

For instance, the <div> element shown above could be represented in JSX as follows:

JSX
<div>
   <h1>A heading</h1>
   <p>A paragraph</p>
</div>

As you can see, the JSX code is almost identical (completely identical in this case) to the corresponding HTML.

Moving on, just like we can have attributes on HTML elements, so can we on JSX elements.

Since a JSX element is merely syntactic sugar over createElement(), its attributes are simply the properties of the object passed into the second parameter of createElement(), that is, the props of the element.

For example, the contenteditable HTML attribute is represented as the contentEditable prop (as we saw above), and likewise as the contentEditable attribute of an element in JSX:

JSX
<h1 contentEditable="true">Hello World!</h1>

Unlike in HTML, however, we can provide dynamic values to JSX attributes instead of mere textual values. This requires us to use the special { } syntax.

As an example, in the following code, we set the className attribute of the <h1> element to a variable textBlue:

JSX
const textBlue = 'text-blue';

const element = (
   <h1 className={textBlue}>Hello World!</h1>
);

We shall learn more about JSX elements, and JSX in general, in the chapter React JSX.

For now, let's discuss more on the intrinsically related idea of props.

What are props?

Consider the following JSX element,

JSX
<h1 contentEditable="true">Hello World!</h1>

and notice the contentEditable attribute.

If we see this same element in terms of a createElement() call, the attribute is merely a property of the object passed as the second argument to the function:

javascript
createElement('h1', { contentEditable: "true" }, 'Hello World!')

contentEditable in both these snippets is a prop of the created <h1> element.

So what exactly is a prop?

In React, a prop is a property of the props object (the second argument) provided to createElement().

As you can probably guess, prop is a fancy word for 'property' in React. This shorthand word 'prop' helps us distinguish other properties in an app from the ones that we provide to React elements while creating them using createElement().

In a createElement() call, all the properties of the second argument object are the element's props. Similarly, in JSX, all the attributes of a JSX element are the props of the corresponding element.

The purpose of props of React elements is much like the purpose of properties of HTML DOM elements, i.e. to customize the element's content, appearance, and/or provide additional data to it.

The nomenclature of many props of React elements that abstract DOM elements is the same as the nomenclature of properties in the DOM. This makes sense because internally, React maps these props to properties of DOM element nodes at one point.

If React innovated a lot in the naming of props of elements abstracting DOM elements, i.e. coming up with different prop names, it would've had to do a substantial amount of processing.

The className prop

Here's a quick example. Consider the following, very common attribute used in HTML: class.

Do you know the name of the corresponding DOM property of element nodes representing the class HTML attribute? Well, it's called className.

To learn why the property is called className and not as class in the DOM; refer to JavaScript HTML DOM — Attributes: className.

The corresponding prop in React is called...you guessed it... className.

In the code below, we showcase an example of className on <h1>:

JSX
const element = (
   <h1 className="blue">React is amazing!</h1>
);

Supposing that the following CSS is set in the HTML file where the React program runs,

CSS
.blue {
   color: blue
}

as soon we launch the page in the browser, we get the following output:

React is amazing!

Not surprisingly, className is an extremely commonly used prop in React apps, just like class is in HTML documents.

The style prop

Besides className, another commonly used prop is style.

Do you remember the style HTML DOM property? Do you remember how it works?

In HTML DOM, the style property of element nodes (in particular, of HTMLElement instances) points to a CSSStyleDeclaration object that we could use to manually set any inline CSS style on a given element.

In React, the style prop works, more or less, the same way.

But since style is a prop that we set ourselves and not a predefined property to refer to (as is otherwise the case with the HTML DOM style property), we obviously can't access styles on it. It just doesn't make any sense!

What we have to do instead is to tell React all the inline styles that we want, in one go.

React expects the value of the style prop to be an object. Each property of this object is internally applied by React to the style property of the corresponding element node in the DOM.

For example, to set the marginLeft and marginTop style properties on the <h1> element in the DOM, we'd do the following (supposing that h1Element holds the <h1> element node):

javascript
h1Element.style.marginLeft = '70px';
h1Element.style.marginTop = '30px';

But in React, we'd do the following:

JSX
<h1 style={{ marginLeft: '70px', marginTop: '30px' }}>Hello World!</h1>

The value of the style prop (or the JSX attribute) here is a JavaScript object literal with two properties: marginLeft defining the margin-left CSS property and marginTop defining the margin-top CSS property.

Notice the double braces, {{ and }}, we have at the beginning and end of the style attribute's value. This might look like new syntax but it's not.

The outer braces represent the special syntax for assigning a dynamic value to an attribute of a JSX element; the inner braces represent the object literal.

To make this more clear, here's an equivalent code:

JSX
<h1 style={ {marginLeft: '70px', marginTop: '30px'} }>Hello World!</h1>

Moving on, React brings a subtle but nice feature to the specification of style properties, especially the ones that deal with absolute length values in pixels, for e.g 10px, -50px, 100px, etc.

This is discussed as follows.

Style properties in React can be set to numbers

The values of style properties in React don't just have to be strings (e.g. '10px'); they could be numbers as well (e.g 10), in which case they're automatically converted to a '<number>px' string internally, where <number> is the number used.

For example, the value 50 would become '50px'; the value 20.55 would become '20.55px'; and so on and so forth.

This can save us from having to do this work manually.

Let's consider a quick example.

In the code below, we set the width of the <h1> element to 100px by providing the width style property the string value '100px':

JSX
<h1 style={{ backgroundColor: 'yellow', width: '100px' }}>Hello World!</h1>
Hello World!

Live Example

But thanks to React, we can simplify this as follows:

JSX
<h1 style={{ backgroundColor: 'yellow', width: 100 }}>Hello World!</h1>

The value of width now is a number, not a string, which is automatically converted to the string '100px' by React.

The output remains the same:

Hello World!

Simply amazing.

Events in React

Let's now talk about events in React, starting with a rudimentary question.

What is the property used to register a click handler on an HTML DOM element called? Well, it's called onclick.

JavaScript
var h1Element = document.querySelector('h1');
h1Element.onclick = function() { /* ... */ };

Now you might be tempted to think that React abides by this exact same naming, but that's NOT the case. Yes, React does call it 'onclick' but with a different casing.

In React, all event-handler props follow the camel casing convention.

This is unlike event handler properties in the DOM and unlike attributes in HTML.

So onclick in React would be called onClick; onmousedown would be called onMouseDown; ontouchstart would be called onTouchStart; and so on and so forth.

That why exactly is this casing used will be explored in the chapter React Events where we'll learn more about how events work in React and why they use W3C's SyntheticEvent API instead of native events.

Therefore, to set up a click listener on an element in React, we ought to use the onClick prop and assign it a function.

Anyways, now that we know that onClick represents the prop used to set up a click event handler on a React element, let's use it.

In the code below, we set up a click event handler on our <h1> element:

JSX
const element = React.createElement(
   'h1',
   { onClick: function(e) { alert('Clicked'); } },
   'Hello World!'
);

As can be seen, the onClick prop is assigned a function, just like we'd do to the onclick property of a DOM element node. The given function simply makes an alert.

Here's the output produced:

Hello World!

Click on the heading and notice an alert made.

Let's now make this a bit more involved by changing the content of the <h1> upon its click.

Inside the handler function, we'll call the render() method of the root object (the same object we used to render the <h1> in the first place, in the previous chapters) to change the content of #root:

JSX
import React from 'react';
import ReactDOM from 'react-dom/client';

const element = React.createElement(
   'h1',
   { onClick: () => {
      root.render(React.createElement('h1', null, 'New content'));
   } },
   'Hello World!'
);

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(element);

Let's see the effect of clicking on the <h1>:

Live Example

As soon as we click the <h1> element, its content indeed changes. This is React in action.

The same code could be expressed in JSX as follows:

JSX
import React from 'react';
import ReactDOM from 'react-dom/client';

const element = (
   <h1 onClick={() => { root.render(<h1>New content</h1>); }}>Hello World</h1>
);

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(element);

The onClick attribute of the <h1> element is assigned a function with the help of a pair of curly braces ({}) (to instruct the JSX parser that the attribute's value is a JavaScript expression). This function calls root.render(), passing it a new <h1> element.

Live Example

Yet again, it works flawlessly.

However, as you might've felt, this code isn't very elegant, not even after the addition of JSX. We are directly triggering the rendering of an <h1> element inside #root when the current <h1> is clicked.

As we keep on adding more and more bells and whistles to this program, the code would just keep on becoming more and more complex and tedious.

For example, let's say we want to extend the program above and make it a counter, whereby the <h1> showcases the current count and also serves as the incrementer for the count, when it's clicked.

Consider the following code where we implement this:

JSX
import React from 'react';
import ReactDOM from 'react-dom/client';

let counter = 0;

function clickHandler() {
   root.render(<h1 onClick={clickHandler}>Count: {++counter}</h1>);
}

const element = (
   <h1 onClick={clickHandler}>Count: {counter}</h1>
);

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(element);

As we click on the <h1> element, a new <h1> element is rendered inside #root.

Notice {counter} and {++counter} in the code above.

Similar to what we saw for JSX attributes above, a pair of curly braces ({}) as part of a JSX element's content represents a JavaScript expression that's resolved and then its resulting value used instead.

For example, Count: {counter} doesn't literally render the text 'Count: {counter}' but instead renders the text 'Count: ' followed by the resolved value of counter. So, let's say if counter is 10, Count: {counter} would be rendered as 'Count: 10'.

By virtue of how reconciliation works in React, technically, rendering a new <h1> element in place of the current <h1> element in the code above doesn't create a new <h1> in the DOM; instead, the same old <h1> is used with a different content. We'll learn more about this later on in this course.

Here's a live working example of the code above:

Live Example

Try clicking on the <h1> element. As you do so, you'll notice the count displayed inside the <h1> change.

Coming back to the discussion, even though this code does its job, this is NOT how React is designed to be run.

Someone could argue that the code could be simplified further to make it look more elegant, as shown below,

JSX
import React from 'react';
import ReactDOM from 'react-dom/client';

let counter = 0;

function incrementCounterAndRender() {
   root.render(<h1 onClick={incrementCounterAndRender}>Count: {counter++}</h1>);
}

const root = ReactDOM.createRoot(document.querySelector('#root'));
incrementCounterAndRender();

but this makes the code even more ugly to read through and maintain.

In short, React was NOT made for us to worry about manually handling rendering concerns, as we're doing in all the code snippets presented thus far in this section.

React could do all of this on its own — in fact, it is meant to do re-rendering on its own. We just need to know how to properly use it when we wish to re-render part of an app. And for that, we ought to know how to work with state.

But before that, we need to know about one of the foundational concepts of React: components.

Components — the cornerstone of React

Components are the cornerstone of React. From day one, React has been based on the idea of components to build the UI.

Now what are components?

Well, there are two ways to define a component, one is completely from the perspective of the UI while the other is more technical and tied to the design of React.

Starting with the former:

A component is a reusable piece of the UI.

Let's consider a webpage. What things could a webpage be composed of? It could have a header, a footer, a section where all the main content goes, maybe even some sidebars, and so on.

As another instance, consider the header. What things could the header be composed of? Well, it could have a logo, a navbar, even a search bar, and so on.

The header, footer, main section, logo, navbar, search bar — essentially everything discussed here — is a component.

As the second example demonstrates, where we have a header component comprised of logo, navbar, and search bar components, components in React can be composed of other components, which can further be composed of components themselves, and so on.

So this is what a component is from a UI perspective. Now, let's define a component in React technically:

A component is a function that returns a React node.

A component is basically a normal JavaScript function that returns back a React node (which we learnt about at the start of this chapter).

It's what allows us to create kind of like a custom element in a React app. For example, recall the header example we gave above which is part of a webpage. It can be denoted as a Header component (more on that later).

Such components are more precisely referred to as functional components, or function components, simply because they are based on functions.

Class components in old React

In older-day React, which still exists and is based on the idea of classes, a component is a class with a render() method that returns a React node.

As you can probably guess, such components are more precisely referred to as class components, simply because they are based on classes (ES6).

Time for an example.

If we want to create a header in a React app, we can easily do so as shown below:

JSX
<header>
   <div className="logo">...</div>
   <nav>...</nav>
</header>

This works but it's NOT reusable. The whole idea of a header isn't encapsulated inside a component. The ultimate solution is to use a React component.

Let's see how to do so.

In the code below, we define a component, i.e. a function, called Header that returns the same JSX that we had above for the header:

JSX
function Header() {
   return (
      <header>
         <div className="logo">The logo</div>
         <nav>The nav</nav>
      </header>
   );
}

This Header function is a component. As its name suggests, it represents a header.

Now if we want to be able to render this component into the webpage, we have to provide it to createElement() (yes, the same createElement() function we've been using so far).

The component goes as the first argument to the method, but keep in mind that we don't call the function; we just provide its reference.

Here's how we'd render the Header component into the #root element:

JSX
import React from 'react';
import ReactDOM from 'react-dom/client';

function Header() {
   return (
      <header>
         <div className="logo">The logo</div>
         <nav>The nav</nav>
      </header>
   );
}

const element = React.createElement(Header, null); const root = ReactDOM.createRoot(document.querySelector('#root')); root.render(element);

createElement(Header, null) serves to instantiate a concrete element out of the Header component (a function) and then the render() method of root renders this instance into the #root element.

Live Example

As we run this code, the dummy text 'The logo' and 'The nav' are displayed on the document, indicating clearly that the <header> element has been rendered out on the document.

If we inspect the component tree produced by the code above in React Developer Tools, here's what we see:

Component tree for the app above in React Developer Tools
Component tree for the app above in React Developer Tools

First we have the Header element and then, within it, the <header> element with its #logo and <nav> elements.

Remember that the component tree in React Developer Tools is not the DOM tree. It showcases the tree of React elements maintained by the underlying app. This is precisely why we have the <Header> element shown in the illustration above, even though it won't be part of the DOM tree.

Moving on, just as we could replace createElement() calls with the corresponding JSX elements, we could do so for components as well.

That is, the same Header component above could be instantiated as follows:

JSX
<Header></Header>

The name of the component, i.e. Header, is used in the starting tag (<Header>) and the ending tag (</Header>).

If we want to, we could even omit the ending tag (</Header>) here, making sure that there is a / at the end of the starting tag, as shown below:

JSX
<Header/>

The following is, however, invalid JSX:

JSX
// Single tag without an ending '/'
<Header>

That's because the <Header> tag doesn't have a corresponding ending tag and neither does it contain / at its end (that is, <Header/>).

Before we conclude this section, there's one more important thing to point out, which we shall explore in more depth in the React Components chapter.

That is, there is a common convention in React apps to create an App component to serve as the entry point into the React application.

JSX
function App() {
   // All our app code goes here.
}

This App component contains all the code of our React app.

It's what's rendered inside the #root element when we run the app:

JSX
import React from 'react';
import ReactDOM from 'react-dom/client';

function App() { /* ... */ }

const element = (
   <App/>
);

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(element);

In the upcoming chapters, we'll be leveraging the App component quite a lot, so it's good to get used to creating it every now and then.

The convention goes way beyond than just a separate App component; it also includes a separate file called App.jsx (or App.js) to host this App component which is then imported into the index.js file we have above. We'll see more details in the React Components chapter.

Now that we know what exactly is a component and how to create one, let's discover the idea of state in React.

State of components

The next exciting thing in React after components is state. Let's start by making the intuition behind state from a theoretical point of view.

The state of a component describes it at a certain point in time.

If you have experience of object-oriented programming in JavaScript, you'd probably already be familiar with the idea of state. The state of an instance of a class describes the instance — it's simply a cohort of some characteristics of the instance.

For example, an instance of a User class might have properties such as name, email, age, etc. These properties collectively define the state of the User instance.

The idea of state is even present in HTML and CSS.

For example, when you hover with the mouse pointer over an element, its state changes to :hover. Similarly, if you focus a given input, its state changes to :focus. The state here describes the element at a certain point in time, i.e. either the element is under the mouse pointer or has active focus.

In user interfaces, the state of a given element describes that element, which in turn affects its visual appearance, its behavior, and/or its content.

For example, a button in a user interface might be 'disabled', an image might 'not be loaded' currently, an accordion might be 'hidden', and so and so forth. These are all the very states of these individual UI components.

The concept of state in React is not any different from this.

In React, the state of a component represents data that influences the component's content, appearance, and/or behavior in one way or the other. More specifically, state is data that a component manages itself.

Difference between state and props

Both state and props in React are means of working with data, yet they differ in where that data is obtained from.

State represents data that a component defines and manages itself. In contrast, props represent data passed on to a component from the outside world — more specifically, from the parent component.

To define the state of a component in React, we use the useState()hook.

We'll learn about hooks in detail in the React Hooks chapter, but to summarize it quickly, a hook is simply a way to 'hook' a component into a given functionality provided by React.

For example, React allows us to define the state of components, and in order to do so, we need to 'hook' them into React's state functionality by leveraging the useState() hook.

The useState() hook allows us define state data of a component in React.

As with createElement(), useState() is defined on the React object that we import into our React app from the react package.

Keep in mind that useState() adds one piece of data to the state of the underlying component. If we wish to add another piece, we ought to make another call to useState().

The initial value of the state defined by useState() is provided as an argument to it. The data can be literally any value in JavaScript: a number, a string, a Boolean, undefined, null, an array, a regex, an object — just about anything!

The most interesting part of working with useState() is its return value.

useState() returns an array whose first element is the value of the corresponding state data and whose second element is a function to update the state to a new value (the main game-changer in React, as we shall see below).

Let's take an example to help understand this all much better.

Consider the following Heading component where we store the text to be shown inside the <h1> as part of the component's state:

JSX
function Heading() {
   const [text, setText] = React.useState('Hello World!');
   return (
      <h1>{text}</h1>
   );
}
  • Firstly, calling useState() sets some state on the Heading component.
  • The argument 'Hello World!' to useState() provides the initial value of this state.
  • The return value of useState() is an array whose first element is the state itself while the second element is a function to update this state.
  • text is merely a convenient name that we use to refer to this state. We could name it anything (it's just an identifier) — content, str, h1Text, html, and so on.
  • setText refers to the state-updater function, which is called in order to update this text state.

Note that it's conventional to name the state-updater function starting with the word 'set', followed by the name of the state.

For example, in the case above, the state was named text, likewise the state-updater function was named setText() (obviously after updating the casing of the state's name, i.e. going from text to Text in setText).

Similarly, if the state was called firstName, then, abiding by this convention, the corresponding state-updater function would be named as setFirstName.

Following this convention, yet again, what would the state-updater functions for the states content and isThemed be called?

  • setcontent and setisThemed
  • set_content and set_isThemed
  • setContent and setIsThemed

Adding state to a component in React is useless if we never ever invoke the state-updater function in order to update that state.

In React, when a state-updater function is invoked, it automatically triggers a re-render of the underlying component (similar to what we were doing manually by calling root.render() to re-render the <h1> element earlier in this chapter).

Let's add a click handler to the <h1> in the code above, via onClick, and call setText() in there to change the text rendered inside the <h1>:

JSX
function Heading() {
   const [text, setText] = React.useState('Hello World!');
   return (
      <h1 onClick={() => { setText('useState() in action') }}>{text}</h1>
   );
}

Open up the following link and click on the <h1> element. You'll notice its content changing upon the click, all thanks to setText().

Live Example

Let's see what exactly happens when setText() gets called:

  • The previous state value, which is 'Hello World!', is replaced with the value 'useState() is amazing'.
  • The Heading component is re-rendered and, likewise, invoked again (remember that it's a function).
  • Inside the Header() function, useState() executes again, this time returning an array whose first element is the latest state data, i.e. 'useState() is amazing', and the second element is the same state-updater function that we had before.
  • This new state data gets stored in text again.
  • text is rendered inside the <h1> element, and consequently we get the text 'useState() in action' displayed.

See how simple and intuitive this code is compared to one we saw ealier where we were manually invoking root.render() in order to change the text inside the <h1>.

This is how React is designed to be used. This is how React thinks about dealing with UI construction. We just tell React to update a particular state; from there onwards, it's all up to React to re-render the component to present the latest state value.

The setText() function above, and in general the state-updater function in React, is reactive. That is, as soon as we call it, a new render is triggered automatically — a reaction is made — and the UI, thereafter, updates as if by magic.

Purely commendable.

One thing worth pointing out here is that instead of accessing useState() as React.useState(), it's typical to access it directly via a named import. Something as follows:

JSX
import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';

function Heading() {
   const [text, setText] = useState('Hello World!');
   return (
      <h1 onClick={() => { setText('useState() in action') }}>{text}</h1>
   );
}

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<Heading/>);

Notice the { useState } named import in line 1 — it serves to introduce a variable called useState into the current module, holding the useState() function exported by react.

In React applications, this named-import approach is quite mainstream for all hooks. Instead of accessing hook functions as React.hookFunction(), the functions are imported directly from the react package and thereafter used as hookFunction().

From this point onwards, we'll follow this very import convention when wanting to use hooks.

Moving on

This chapter touched on a lot of different ideas in React, which are fundamental for you to understand to be able to effectively build complex React apps without running into glitches.

However, there are tons and tons of intricate details left off deliberately here for the sake of brevity. Certainly, if we were to cover everything rightaway at this beginning stage, it would become too overwhelming and tedious to follow.

We'll explore all of this intricacy, to its very core, in the upcoming chapters.

For now, it's super important that you experiment with useState() to implement simple, elementary programs. They may seem elementary, for sure, but the more you code them, the better you'll become in React.

The upcoming two exercises get you to code such programs using all of the knowledge that you obtained thus far in this course. And even before that, up next we have a React Basics quiz ready for you to test your comprehension of this chapter.

Spread the word

Think that the content was awesome? Share it with your friends!

Join the community

Can't understand something related to the content? Get help from the community.

Open Discord

 Go to home Explore more courses