React: Using the State Hook
Tags: react, javascript, tutorial
Published: 2020-07-16 19:21:11

In my first post in this series I said:

> we'll be needing to use a class later, to get access to states

It turns out I was wrong. This was once the case but the React team have remedied it with `Hooks`. I discovered `Hooks` thanks to this post.

{% post https://dev.to/josesrodriguez610/react-hooks-implementation-of-usestate-1hl1 %}

## What are `Hooks`?

Let's look at how the React documentation describes `Hooks`.

>A `Hook` is a special function that lets you “hook into” React features. For example, `useState` is a `Hook` that lets you add React state to function components.

## Converting Classes

I'm going to convert my old `class`, MaterialSwitch, from React: A simple start into a functional component. It will work exactly the same but, should, use less code and run a little quicker (as it doesn't have to load in all of React)

### Render

Our old render function will become our whole MaterialSwitch function.

```JS
render() {
  const {children, readOnly, disabled, defaultChecked } = this.props;
  return (
    <label className="md_switch">
      <input 
        readOnly={readOnly}
        disabled={disabled}
        defaultChecked={defaultChecked}
        onChange={this.changeHandler}
        type="checkbox" 
      />
      <span className="md_switch__toggle"></span>
      {children}
    </label>
  )
}
```

Because we're now using a `function` and not a `class` we need to pass in `props` and `this.props` will become `props` but that's all we need to worry about right now.

```JS
function MaterialSwitch(props) {
  const {children, readOnly, disabled, defaultChecked } = props;
  return (
    <label className="md_switch">
      <input 
        readOnly={readOnly}
        disabled={disabled}
        defaultChecked={defaultChecked}
        onChange={this.changeHandler}
        type="checkbox" 
      />
      <span className="md_switch__toggle"></span>
      {children}
    </label>
  )
}
```

### Constructor

The constructor this contains `super`, default states and the binding of `this` to a function. We don't need any of these so let's delete that.

```js
constructor(props) {
  super(props);
    
  this.state = {
    checked: props.defaultChecked
  }

  this.changeHandler = this.changeHandler.bind(this);
}
```

We do still need to do something with the state though, so let's look at `useState`. `useState` is a function that returns two values, a reference to the current state and a function to update it. Because it returns two values we'll use [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to save those values.

The naming convention that is most common, for our two values, is `[stateName, setStateName]`. Which will leave us with `stateName` containing the value and `setStateName` being the function to update it.

The last thing to note about the `useState` function is that it takes one argument, the default/initial state. Now we know all that we can boil our `checked` state down to this, which will appear in the function.

```js
function MaterialSwitch(props) {
  const {children, readOnly, disabled, defaultChecked } = props;
  // This is our new line
  const [checked, setChecked] = React.useState(defaultChecked);
  return (
    <label className="md_switch">
      <input 
        readOnly={readOnly}
        disabled={disabled}
        defaultChecked={defaultChecked}
        onChange={this.changeHandler}
        type="checkbox" 
      />
      <span className="md_switch__toggle"></span>
      {children}
    </label>
  )
}
```

### Functions

We only had one function in the `class` version but we'll still need to move that into our new main function.

```js
changeHandler(event) {
  const { onChange } = this.props;
  this.setState({checked: event.target.checked});

  If(typeof onChange === "function") onChange(event);
}
```

As we know `this.setState();` becomes `setStateName();`, `onChange` needs to be declared when we declare all our `props` and the reference to `changeHandler` drops the `this` but that's it.

```js
function MaterialSwitch(props) {
  // We added onChange to this line
  const {children, readOnly, disabled, defaultChecked, onChange } = props;
  const [checked, setChecked] = React.useState(defaultChecked);

  // Here is our function
  const changeHandler = function(event) {
    setChecked(event.target.checked);

    if(typeof onChange === "function") onChange(event);
  }

  return (
    <label className="md_switch">
      <input 
        readOnly={readOnly}
        disabled={disabled}
        defaultChecked={defaultChecked}
        // We had to change this reference to the function too
        onChange={changeHandler}
        type="checkbox" 
      />
      <span className="md_switch__toggle"></span>
      {children}
    </label>
  )
}
```
And that's everything moved over. The original `class` version was 35 lines of code and this, new, `functional` version is only 24. Shaving off 11 lines of code might not seem like a lot but it soon adds up.

{% jsfiddle https://jsfiddle.net/link2twenty/79vkywt8/ js result %}

## Wrapping up
And there we have it, what started as a gap in my knowledge became a great learning experience, there is much more for me to learn about hooks and I'm sure I'll cover what I learn in the future.

Thank you so much for reading and, as always, feel free to post questions or corrections in the comments below. If you have any posts you want me to read feel free to post them too, I'm always interested to see other stuff. Thanks again!
🦄🧠💕🦄🦄💕❤🧠💕❤