React: A simple start
Tags: react, a11y, javascript, tutorial
Published: 2020-07-10 21:29:32

Recently I've been learning react, I'm by no means an expert but I enjoy teaching as I learn. It's a great way to help people learn, cement what I've learnt and also get some feedback on what I may not have understood. As I'm still a learner I'll be converting an old project of mine over to react, the project I've chosen is [material design switches](https://dev.to/link2twenty/accessibility-first-toggle-switches-3obj).

{% link https://dev.to/link2twenty/accessibility-first-toggle-switches-3obj %}

The aim is to be able to just write a single HTML tag and get a simple, nice and accessible toggle switch back. I'll be using JSFiddle to show the various steps.

```html
<MaterialSwitch>Toggle switch</MaterialSwitch>
```
![example](https://thepracticaldev.s3.amazonaws.com/i/tb83a5m5g4eyckyb7kg3.png)

## Setup

First things first, let's make a quick `hello world!`. I know we can use a [react functional component](https://reactjs.org/docs/components-and-props.html#function-and-class-components) rather than a full class while we're at this simple stage but we'll be needing to use a class later, to get access to states, so let's start with one.

The class needs to extend `React.Component` and just needs the `render()` function. Here it is.

{% jsfiddle https://jsfiddle.net/link2twenty/k7fmpqxu/12/ js result %}

```js
ReactDOM.render(<MaterialSwitch />, document.querySelector("body"))
```
You'll notice I have this line at the end for this demo we can pretend it's the same as having `<MaterialSwitch />` in the html.

## Create

Now let's actually think about the component we want to create, it's a checkbox so we need;
 - Label text `child` - text to appear next to checkbox
 - readOnly `property` - is the checkbox readOnly?
 - disabled `property` - is the checkbox disabled?
 - defaultChecked `property` - checked state on load
 - checked `state` - internal checked state

I think that's all we will need, I've got 3 different labels `child`, `property` and `state`. Both children and properties are passed in from a higher level and the component does not have any control over them, they simply exist. States however can be changed from within a component and are the beauty of React.

### Adding State and Props

Because we want to use states we're going to need to use the constructor function. When you use the construction function you need to be sure to pass `props` to the `super` function in order to keep things working right.

```js
constructor(props) {
  /**
   * This is the super function it ensures
   * the constructor function still carries
   * out it's original purpose.
  */
  super(props);

  /*
   * Here I am setting up the default states
   * I am setting "checked" to be equal to 
   * the property "defaultChecked"
  */
  this.state = {
    checked: props.defaultChecked
  }
}
```

We're also going to want to copy in our HTML from the existing project but with a few React changes.

```js
render() {
  // This is how get our props, we could have
  // done this.props.readonly for each place
  // we wanted to use the props but I think 
  // this is easier to understand
  const {children, readonly, disabled, defaultChecked } = this.props;
  return (
    <label className="md_switch">
      <input 
        readonly={readonly}
        disabled={disabled}
        defaultChecked={defaultChecked}
        type="checkbox" 
      />
      <span className="md_switch__toggle"></span>
      {children}
    </label>
  )
}
```
Anywhere you want to use a variable in the `HTML`, well [JSX](https://reactjs.org/docs/introducing-jsx.html) techically, just place the variable name inside some braces like so `{variable}`.

It's also worth pointing out, anywhere where you might want to add a `class` to your element you'll have to use `className` rather than the standard `class` this is because `class` is a reserved word in javascript.

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

### Adding functions

All we need from our function is for it to update the state when the checked attribute of the checkbox changes. The function will be easy enough to write but there are another couple of things we'll need to do to get it all working.

```js
/**
 * Update checked on change
 *
 * @param {Event} event - from the changed element
*/
changeHandler(event) {
  this.setState({checked: event.target.checked})
}
```
Simple enough, set the checked state to the target of the event's checked param. Now let's link it up to the `HTML`/`JSX`.
```js
render() {
  const {children, readonly, disabled, defaultChecked } = this.props;
  return (
    <label class="md_switch">
      <input 
        readonly={readonly}
        disabled={disabled}
        defaultChecked={defaultChecked}
        onChange={this.changeHandler}
        type="checkbox" 
      />
      <span class="md_switch__toggle"></span>
      {children}
    </label>
  )
}
```
To add a function to the event you just need to add the onEvent tag, we want to trigger on change so we'll use `onChange` (notice the camelCase).

This still won't work though as within `this.changeHandler` the context of `this` has been changed to the `event`. To ensure the context of `this` remains bound to our react component we need to add the following line to our constructor function.
```js
this.changeHandler = this.changeHandler.bind(this);
```
{% jsfiddle https://jsfiddle.net/link2twenty/casrhtwk/ js result %}

### Events
For the last bit of JS we're going to want to allow users of our component to use events, so we'll pass our events back up using `props`. As we're already using the `onChange` event we'll need to modify our function to sent the event up further.

```js
/**
 * Update checked on change
 *
 * @param {string} text
*/
changeHandler(event) {
  const { onChange } = this.props;
  this.setState({checked: event.target.checked});
   
  If(typeof onChange === "function") onChange(event);
}
```
I get `onChange` from props and now we can pass the event up. I've added the `typeof` function just in case the user adds something strange or even nothing at all.

The `HTML`/`JSX` bit is a lot easier we just need to pass our prop on like so

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

## Styling
Styling is as simple as adding our CSS I won't go over the CSS as it's exactly the same as the original post I was recreating. So here it is.

{% jsfiddle https://jsfiddle.net/link2twenty/k7fmpqxu/43/ css result %}

## Wrapping up
Well there we have it, we have made our first react component. We have a simple tag that can used to input a material toggle.

Let's look at the `HTML` and the final result. 

```html
<div>
  <MaterialSwitch>Toggle Switch</MaterialSwitch>
  <br />
  <MaterialSwitch defaultChecked>Pre-activated</MaterialSwitch>
  <br />
  <MaterialSwitch disabled>Disabled</MaterialSwitch>
  <br />
  <MaterialSwitch defaultChecked disabled>
    Activated and disabled
  </MaterialSwitch>
  <br />
  <MaterialSwitch>
    Really really really long label
    content to hopefully span several lines
    to show that the checkbox will stay central.
  </MaterialSwitch>
</div>
```

{% jsfiddle https://jsfiddle.net/link2twenty/k7fmpqxu/48/ result %}

And that's it, we're home free, thanks for reading. If you have any questions, suggestions or just wanna chat feel free to comment down below. Thanks again!

🦄🧠💕🦄🦄💕❤🧠💕❤