React Fundamentals
Tags: react, javascript, jsx, codenewbie
Published: 2020-09-17 10:51:14

In this article, I will discuss very basic React fundamentals. Knowing basic javascript is good enough to follow along with the article. Even though you have been working with React for some time, you might learn some new things or justifications for certain things that you already know from this article.

> This article is HEAVILY based on [React Fundamentals workshop](https://github.com/kentcdodds/react-fundamentals) by [Kent C Dodds](https://kentcdodds.com/) which will also be a part of [Epic React](https://epicreact.dev/) course soon to be released. If you are more like a `learning by doing` type of person similar to me, head over to the [React Fundamentals](https://github.com/kentcdodds/react-fundamentals) repo and follow the instructions in the README. This article is more or less a compilation of things in that repo with my own explanations. I will add some more things to this article in the future based on feedback.

Table of Contents
- [Basic JavaScript-rendered Hello World](#basic-javascript-rendered-hello-world)
- [Intro to raw React APIs](#intro-to-raw-react-apis)
    - [React.createElement()](#reactcreateelement)
- [Using JSX](#using-jsx)
    - [Interpolation in JSX](#interpolation-in-jsx)
    - [Conditionals and Loops](#conditionals-and-loops)
- [Creating custom components](#creating-custom-components)
    - [PropTypes](#proptypes)
    - [React Fragments](#react-fragments)
- [Styling](#styling)
    - [Inline CSS](#inline-css)
    - [Regular CSS](#regular-css)
- [Forms](#forms)
    - [Using Refs](#using-refs)

## Basic JavaScript-rendered Hello World
Let's see how to render Hello World using basic javascript.

My HTML contains a single `div` with `id` as `root`
```html
<div id='root'></div>
```

Now, I want to add `<div class='container'>Hello World</div>` to that root div.

We can do that using javascript's document API. Let's see how
```js
// Fetching the root div element
const rootElement = document.getElementById('root')

// Creating a new div as per our requirements
const divElement = document.createElement('div')
divElement.textContent = 'Hello World'
divElement.className = 'container'

// Appending newly created div element to the root element.
rootElement.append(divElement)
```

What we are doing here is very simple.
1. Get a reference to the actual DOM root element
1. Create a new div element using `document.createElement` and then set its class and textContent
1. Append this newly created element to the root div element.

This produces the following HTML markup.
```html
<div id='root'>
    <div class='container'>Hello World</div>
</div>
```


## Intro to raw React APIs
Now let's try to use React's raw APIs to create markup that we need instead of (vanilla) javascript.

We need two important APIs to achieve our task. In vanilla javascript. they are:
```js
document.createElement()
rootElement.append(domElement)
```

The React's equivalent of these two APIs are:
```js
React.createElement()
ReactDOM.render(reactElement, rootElement)
```

Let's see `React.createElement()` in more detail.

### React.createElement()
This accepts three parameters
1. Component or Tag to use to create the element
1. Props for the component
1. Children

The API looks like `React.createElement(component, props, ...children)`

So, to create an element like `<div class='container'>Hello World</div>`, you would do 
```js
React.createElement('div', { className: 'container' }, 'Hello World')
```

Our HTML will have
```html
<div id="root"></div>
```

Now, to append `<div class='container'>Hello World</div>` to the root element using React, we do:
```js
const rootElement = document.getElementById('root')

const divElement = React.createElement('div', {className: 'container'}, 'Hello World')

ReactDOM.render(divElement, rootElement)
```

Can you see how similar the React's API is to the normal vanilla js document API? 

Note that, you can even create nested elements using this.

For example, let's try to create the following markup.
```html
<div class='container'>
    <span>Hello</span>
    <span>World</span>
</div>
```

To create the above markup
```js
const rootElement = document.getElementById('root')

const helloElement = React.createElement('span', null, 'Hello')
const worldElement = React.createElement('span', null, 'World')
const divElement = React.createElement('div', {className: 'container'}, helloElement, worldElement)

ReactDOM.render(divElement, rootElement)
```

You can even use a special `children` prop to add the children like the following
```js
React.createElement('div', {className: 'container', children: [helloElement, worldElement]})
```
The above code is same as the below code
```js
React.createElement('div', {className: 'container'}, helloElement, worldElement)
```


## Using JSX
If you have already been using React or saw the React code any time, you most probably would not have seen `React.createElement` being used. Instead, you might have seen some code that looks similar to HTML. Let's see what it is.

JSX is HTML-like syntactic sugar on top of raw React APIs. 

Let's see an example.

```js
const divElement = <div id='container'>Hello World</div>
```

The above code is equivalent to 
```js
const divElement = React.createElement('div', {id: 'container'}, 'Hello World')
```

But JSX is not a valid javascript code, so we use a compiler called `Babel` to convert JSX code to its corresponding `React.createElement` code.

Now, let's see how easy it is to create the following markup using JSX.
```html
<div class='container'>
    <span>Hello</span>
    <span>World</span>
</div>
```

```js
const rootElement = document.getElementById('root')

const divElement = <div className='container'><span>Hello</span><span>World</span></div>

ReactDOM.render(divElement, rootElement)
```

Note that there are some subtle differences between JSX and HTML. 

For example, in HTML to add class to an element, we add it like `class='container'`, whereas in JSX, we need to write `className='container'`. 

There are some other differences when using JSX which I will explain later in the post.

## Interpolation in JSX
Since JSX is written in javascript itself, there are some very interesting things which you can do. One of those is using JSX interpolation. It basically gives us the ability to use javascript inside of JSX. Whenever you do interpolation, you would surround it with `{` and `}`. This tells the Babel compiler that interpolation is being used here.

For example, take the following code
```js
const divElement = <div className='container'>Hello World</div>
```

Now, you want the class name and text content to be dynamic, you can do something like
```js
const divClassName = 'container'
const divTextContent = 'Hello World'

const divElement = <div className={divClassName}>{divTextContent}</div>
```

Can you see the flexibility that interpolation gives us? 

### Conditionals and Loops
You can even add conditionals and loops in JSX
```js
{ condition ? <div>Hello World</div> : <div>Goodbye World</div> }
```
As you can see above, to use conditionals in JSX, you would make use of the tertiary operator.

```js
{items.map((item) => <div key={item.id}>{item.title}</div>)}
```
To use loops, you will use the `map` function.

You can even use template literals in JSX like
```js
const element = <div id={`item-${itemId}`}>{itemContent}</div>
```
To learn more about JSX, head over to [JSX in Depth](https://reactjs.org/docs/jsx-in-depth.html) - React's official docs

## Creating custom components
Consider the following JSX code
```html
<div className='container'>
  <div className='message'>Hello World</div>
  <div className='message'>Goodbye World</div>
</div>
```
Here you can see the code `<div className='message'></div>` is duplicated at two places.

To avoid duplication, the simplest thing we can do is to create a function and then call it instead.

```js
function message(text) {
    return <div className='message'>{text}</div>
}
```
```html
<div className='container'>
    {message('Hello World')}
    {message('Goodbye World')}
</div>
```

Let's refactor this a bit.
```js
function message({children}) {
    return <div className='message'>{children}</div>
}
```
```html
<div className='container'>
    {message({children: 'Hello World'})}
    {message({children: 'Goodbye World'})}
</div>
```

Let's refactor this even more to use React.createElement
```js
function message({children}) {
    return <div className='message'>{children}</div>
}
```
```html
<div className='container'>
    {React.createElement(message, null, 'Hello World')}
    {React.createElement(message, null, 'Goodbye World')}
</div>
```
Previously in all the examples that we have seen, the first argument of React.createElement() is a string like 'span' or 'div'.

But React.createElement also accepts a function that returns something renderable like JSX, some string, number etc.

That's why the above code works.

Now, let's convert the above code to JSX
```js
function message({children}) {
    return <div className='message'>{children}</div>
}
```
```html
<div className='container'>
    <message>Hello World</message>
    <message>Goodbye World</message>
</div>
```
The above code seems to be perfect, right? Actually it's not. The above code will not work as intended. The reason being how babel compiles the JSX code to it's corresponding React.createElement() code.

`<message />` is compiled by babel to `React.createElement('message')`. But what we want is `React.createElement(message)`. In the first case, the first argument is a string, in the second case, it's a function.

For the babel to convert it into what we needed, we have to make the `message` function name uppercase.

```js
function Message({children}) {
    return <div className='message'>{children}</div>
}
```
```html
<div className='container'>
    <Message>Hello World</Message>
    <Message>Goodbye World</Message>
</div>
```
Now, this `<Message>Hello World</Message>` will be compiled to `React.createElement(Message, {children: 'Hello World'})`, which is exactly what we needed.

Check the below examples to see how Babel compiles each of the JSX formats.

| JSX                    	                | React.createElement()                   	                |
|---------------------------- |------------------------------------------------|
| `<Capitalized />`        	        | `React.createElement(Capitalized)`        	        |
| `<property.access />`    	| `React.createElement(property.access)`    	|
| `<Property.Access />`    	| `React.createElement(Property.Access)`    	|
| `<Property['Access'] />` 	| `SyntaxError`                             	                        |
| `<lowercase />`          	| `React.createElement('lowercase')`        	        |
| `<kebab-case />`         	| `React.createElement('kebab-case')`       	|
| `<Upper-Kebab-Case />`  	| `React.createElement('Upper-Kebab-Case')` 	|
| `<Upper_Snake_Case />`   | `React.createElement(Upper_Snake_Case)`   	|
| `<lower_snake_case />`   	| `React.createElement('lower_snake_case')` 	|

So, we can see that the component name needs to be UpperCamelCased for it to work as intended.

### PropTypes
Let's slightly change the previous message component so that it accepts `name` prop.

```js
function Message({name}) {
    return <div className='message'>Hi, your name is {name}.</div>
}
```
```html
<Message name='foo' />
<Message />
```

This produces
```
Hi, your name is foo.
Hi, your name is .
```

This doesn't look good. Does it? So what if there is a way we can enforce that the name needs to be passed and it needs to be a string.

Luckily, React gives us a way to do that using `PropTypes`.
Let's create a `PropType` to enforce the type of `name` to be `string`.
```js
const PropTypes = {
    string(props, propName, componentName) {
        if (typeof props[propName] !== 'string') {
            return new Error(`In component ${componentName}, ${propName} needs to be a string, but it was of type ${typeof props[propName]}`)
        }
    },
}

function Message({name}) {
    return <div className='message'>Hi, your name is {name}.</div>
}

Message.propTypes = {
    name: PropTypes.string,
}
```
Now every time you pass anything other than `string` for `name` prop, it throws an error.

Since cases like these are so common, the `React` team developed a library called [prop-types](https://github.com/facebook/prop-types) which you can use in a similar way - `PropTypes.string.isRequired`.  Check out the [repo](https://github.com/facebook/prop-types) for more details.

Note that PropTypes will be disabled in a production environment for performance reasons.

### React Fragments
```html
<div id='root'></div>
```
Let's consider the following use case.
You have to add `<span>Hello</span>` and `<span>World</span>` to the `rootElement` using React.

In the end, the markup should look like
```html
<div id='root'>
    <span>Hello</span>
    <span>World</span>
</div>
```
Let's see if we can do this.
```js
const rootElement = document.getElementById('root')

const elementOne = React.createElement('span', null, 'Hello')
const elementTwo = React.createElement('span', null, 'World')

ReactDOM.render(?????, rootElement)
```
Now, what should be in the place of `?????` in the last line. It can neither be `elementOne` nor `elementTwo`, because we want both of them to be rendered (not one). But `ReactDOM.render()` takes only one react element as an argument and then appends it to rootElement.

One way to achieve this is if we can wrap both of the elements in a new element.

```js
const rootElement = document.getElementById('root')

const elementOne = React.createElement('span', null, 'Hello')
const elementTwo = React.createElement('span', null, 'World')

const combinedElement = React.createElement('div', null, elementOne, elementTwo)

ReactDOM.render(combinedElement, rootElement)
```

The above code may look fine, but it produces different HTML than what we needed.
```html
<div id='root'>
    <div>
        <span>Hello</span>
        <span>World</span>
    </div>
</div>
```

This is the reason why you can't do something like the following in your code.

```js
function Message() {
    return <span>Hello</span><span>World</span>
}
```
Because there is no way for babel to be able to convert this to a single React.createElement()

React Fragments are introduced in `React v16.2.0` exactly to solve this problem. Now you can return multiple elements by just wrapping them around with `React.Fragment`.

For example,
```js
function Message() {
    return (
        <React.Fragment>
            <span>Hello</span>
            <span>World</span>
        </React.Fragment>
    )
}
```

React will ignore this `React.Fragment` when rendering.

So the previous problem can be solved now in the following way.

```js
const elementOne = React.createElement('span', null, 'Hello')
const elementTwo = React.createElement('span', null, 'World')

const combinedElement = React.createElement(React.Fragment, null, elementOne, elementTwo)

ReactDOM.render(combinedElement, rootElement)
```

There is a short hand representation for `React.Fragment`. 

Instead of writing `<React.Fragment>{childrent}</React.Fragment>`, you can write something like `<>{children}</>`. Both yield absolutely same result.

## Styling
There are two general ways to style React components.
1. Inline CSS
1. Regular CSS

Let's see inline CSS first

### Inline CSS
In normal HTML too, you can add inline styles to your HTML elements by adding your styles as a string to `style` attribute.
```html
<div style="color: red; font-style: italic;">Red Italic Text</div>
```

In `React` also you would add your styles to `style` prop, but instead of a `string`, `style` prop accepts an `object`.

For example,
```js
const elementStyle = {
    color: 'red',
    fontStyle: 'italic'
}
```
```html
<div style={elementStyle}>Red Italic Text</div>
```
You can even inline `elementStyle` if you like
```html
<div style={{ color: 'red', fontStyle: 'italic' }}>
    Red Italic Text
</div>
```

Another difference with styles in React from that of HTML is property names needs to be `camelCased` instead of `kebab-cased`. For example, in React styles, `background-color` will become `backgroundColor`, `font-style` will become `fontStyle`, etc.

Also the value of the style property is always `string` or `number`(since `style` needs to be a proper javascript object, things like `#fff` or `20px` are not proper javascript values). So you cannot write something like `fontSize: 20px`, instead you need to write `fontSize: '20px'`. Similarly you cannot write `color: #fff`, you need to write `color: '#fff'`.

### Regular CSS 
Using regular css is straight forward. You just add the classNames and ids that you need and then style your elements using those accrodingly.


## Forms
Consider the following form
```html
<form>
  <div>
    <label htmlFor="usernameId">Username:</label>
    <input id="usernameId" type="text" name="username" />
  </div>
  <button type="submit">Submit</button>
</form>
```

Now handling forms in React is very similar to how we do in normal javascript. You just define a submit handler and then assign it to the onSubmit event of the form.

```js
function handleSubmit(event) {
    event.preventDefault()
    // You can get the value of username in one of the following ways.
    // event.target.elements[0].value
    // event.target.elements.usernameId.value
    // event.target.elements.username.value
   // Do whatever you want with the username
}
```

### Using Refs
There is another way to get the reference to an element in React - using Refs.
Refs are special objects in react that stays consistent between rerenders of the component and also changing it will not cause the component to rerender.

You can create a Ref using `React.useRef()`

```js
const myRef = React.useRef()
```
Refs will have a `current` property which contains the value of ref. If you assign a `ref` to a React element, `ref.current` will automatically have the reference to the object.

For example
```html
<input ref={myRef} />
```
Now `myRef.current` will have reference to that input element.

Let's make use of ref to get the username in our form.
```js
function UsernameForm() {
  const usernameInputRef = React.useRef()

  function handleSubmit(event) {
    event.preventDefault()
    // usernameInputRef.current.value will have the value of the input
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="usernameInput">Username:</label>
        <input id="usernameInput" type="text" ref={usernameInputRef} />
      </div>
      <button type="submit">Submit</button>
    </form>
  )
}
```
Go through [useRef - official docs](https://reactjs.org/docs/hooks-reference.html#useref) to learn more about refs.

There is more to learn about React Forms. Go through [official docs](https://reactjs.org/docs/forms.html) to learn more.

> This article is HEAVILY based on [React Fundamentals workshop](https://github.com/kentcdodds/react-fundamentals) by [Kent C Dodds](https://kentcdodds.com/) which will also be a part of [Epic React](https://epicreact.dev/) course soon to be released. If you are more like a `learning by doing` type of person similar to me, head over to the [React Fundamentals](https://github.com/kentcdodds/react-fundamentals) repo and follow the instructions in the README. This article is more or less a compilation of things in that repo with my own explanations. I will add some more things to this article in the future based on the feedback that I receive.

Did you learn anything new from this article? Tell me in the comments.

**Links and References**
- [React Fundamental Workshop](https://github.com/kentcdodds/react-fundamentals) by [Kent C Dodds](https://kentcdodds.com/)
- [Epic React](https://epicreact.dev/)
- [Beginner's Guide to React](https://kcd.im/beginner-react)
- [React Documentation](https://reactjs.org/docs/getting-started.html)
- [React Without JSX](https://reactjs.org/docs/react-without-jsx.html)
- [Introducing JSX](https://reactjs.org/docs/introducing-jsx.html)
- [JSX in Depth](https://reactjs.org/docs/jsx-in-depth.html)
- [Typechecking with PropTypes](https://reactjs.org/docs/typechecking-with-proptypes.html)
- [React Fragments](https://reactjs.org/docs/fragments.html)
- [Inline Styles](https://reactjs.org/docs/dom-elements.html#style)
- [Styling and CSS](https://reactjs.org/docs/faq-styling.html)
- [Forms](https://reactjs.org/docs/forms.html#gatsby-focus-wrapper)
- [useRef](https://reactjs.org/docs/hooks-reference.html#useref)

> ## Other articles of mine that you might like
- [Create Your Own Super Simple URL Shortener](https://blog.bhanuteja.dev/create-your-own-super-simple-url-shortener)
- [Why you should start using HSL color format](https://blog.bhanuteja.dev/why-you-should-start-using-hsl-color-format)
- [Hyphenate when you justify text](https://blog.bhanuteja.dev/til-hyphenate-when-you-justify-text)
- [Embed Youtube Videos into Your Markdown Editor](https://blog.bhanuteja.dev/embed-youtube-videos-into-your-markdown-editor)
- [Babel Plugin To Remove Console Logs In Production](https://blog.bhanuteja.dev/babel-plugin-to-remove-console-logs-in-production)
- [noopener, noreferrer, and nofollow - When to use them? How can these prevent Phishing Attacks?](https://blog.bhanuteja.dev/noopener-noreferrer-and-nofollow-when-to-use-them-how-can-these-prevent-phishing-attacks)
- [Create New CodePens and CodeSandboxes Instantly With ZERO clicks](https://blog.bhanuteja.dev/create-new-codepens-and-codesandboxes-instantly-with-zero-clicks)
- [How to Import SVGs into your Next.js Project?](https://blog.bhanuteja.dev/how-to-import-svgs-into-your-nextjs-project)
- [Create Custom Markdown Parser](https://blog.bhanuteja.dev/create-custom-markdown-parser)
- [Optimize Your Website For Social Media Platforms](https://blog.bhanuteja.dev/optimize-your-website-for-social-media-platforms)
- [Add Typescript to your Next.js project](https://blog.bhanuteja.dev/add-typescript-to-your-nextjs-project)

[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/J3J72JK30)