30 Days Of JavaScript

Day 30: React

Lesson 2: State

When state (data) changes in our app, React will work out what needs to be updated in the DOM for us. It knows what has changed by monitoring data that we say are state.

State is a fancy name for data that we care about. Broadly speaking, if some piece of start changes then react will reinvoke the function that creates the component. In this case the App() function.

Let's add some state and change it.

React allows us to add functionality to components with things called hooks. The hook we care about here is the useState hook.

Change your App.js to look like this:

1import React, { useState } from "react";
2import "./style.css";
3
4export default function App() {
5  const [count, setCount] = useState(0);
6
7  return (
8    <div>
9      <h1>Hello All The Code!</h1>
10      <p>Start editing to see some magic happen :)</p>
11    </div>
12  );
13}

Note changed import at the top and the new line at the start of the function.

useState() returns an array with two elements. The first is the value of the data it is managing, the second is a function to use to update that data. Notice how we are using destructuring to access those two returned values, this is a very common patter in React.

If you pass an argument into useState() this will set the initial value.

So in this case we have set a const called count to 0. Even though we will be changing count we create it as a const because we won't update it directly. We will use setCount to do that.

Now add a this in place of the code currently in between the <div> tags:

1<div>Count: { count }</div>
2<button onClick={onHandleClick}>Add 1</button>

We will create the onHandleClick function in a minute.

The first line here uses { count } to display the value of the count constant. While this all looks like HTML it's not really, it's JSX, which is just a weird flavour of JavaScript. This means we can add JavaScript in anywhere we want just by putting in some curly braces 😀

The second line is a button with an onClick handler. Here is another clue that this is JSX and not HTML. In HTML this would have been onclick but because this is JSX we use onClick instead - and yes, many React developers have lost hours wondering why events aren't firing thanks to this, for either forgetting the capital letter in React or adding the capital in HTML (usually the latter since it fails silently without an error 🤦‍♂️)

Now add this function above the return line and after useState line:

1const onHandleClick = () => {
2  setCount(count + 1);
3};

This is the event handler function that calls the setCount function with a new value. We pass in count + 1. What we can't do is change count directly and then pass it in.

So this is no good:

1const onHandleClick = () => {
2  count = count + 1;
3  setCount(count);
4};

This would be ok though:

1const onHandleClick = () => {
2  const newCount = count + 1;
3  setCount(newCount);
4};

So long as the only thing that sets count is setCount then you're good.

When you save that you can click the button and watch the count change.

Even with this small example I think you can see why React is so popular. We didn't need to use document.getElementById or any of that rubbish.

You change the data and the UI updates, that's declarative programming for you.

Before we move on to the next lesson I want you to delete the <div> and </div in the return block of App().

You will immediately see this error:

1JSX expressions must have one parent element.

This means that you can't have two JSX components next to each other at the top of a return.

If you don't want to wrap them in a <div> like we have here, which will appear in the DOM, you can use a fragment instead, which is just an empty set of tags.

1<>
2  <div>Count: {count}</div>
3  <button onClick={onHandleClick}>Add 1</button>
4</>

This is because under the hood React is calling functions and a function can't return more than one thing, having two JSX tags next to each other at the top level, is like trying to return two things from a function. You need to wrap them in another, single JSX tag at the top level to solve this.

Outline

Go Pro?

If you upgraded to pro, sign in here

  • About
  • Blog
  • Privacy
Looking to email me? You can get me on my first name at allthecode.co