---
title: React Essentials
author: Garen Ikezian
---
# What is a Component?
Components in React is a JavaScript function that returns an HTML markup thereby allowing you to create reusable web templates/code. It is one of the key foundations in React and they always start with an uppercase letter to distinguish from vanilla HTML tags.
```js
function SomeComponent(){
return (
This is a header
)
}
export default function Main(){
return(
)
}
```
Important stuff to know in React:
- **JSX**: It is an extension of HTML for Javascript. It is a convenient tool to have HTML tags inside a JavaScript file.
- **Babel**: A transcompiler to make the new stuff in ECMAScript 2015+ or ES6 (some JavaScript version) to be backwards compatible to ES5. Since Babel can also understand JSX, it is used by React to transcompile its components.
Ex:
```js
// Babel Input: ES2015 arrow function
[1, 2, 3].map(n => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
```
- **Props**: It is short for "properties". They are static parameters of componenets (they are seen attributes in HTML tags). They are usually made for rendering purposes.
Ex:
```js
export default function Main(props) {
return (
We serve the most {props.adjective}{" "}
food around.
);
}
function App() {
return (
);
}
```
- **State**: It is a dynamic property (unlike regular static properties). It helps a component "remember" information and are used to keep track of something.
States are not functions, they are just snapshots of data that changes with every render.
# What is a Hook?
Hooks in React are a function and are used to handle states for components. It is a convention for hooks to start with the word "use".
There are different types of hooks. Some are built-in and some are custom made.
# Understanding useState(), useEffect(), useReducer(), and useRef() Hooks
## [useState()](https://react.dev/reference/react/useState)
`useState` is a hook that adds a state to a component.
Syntax:
```js
const [state, setState] = useState("state value");
```
`useState` returns an array of two values.
1. The value of the state.
2. The `set` function that lets you change the value of that state.
It's like a compact getter and setter method in Java or C#.
### Usage:
`useState()` is best suited with user events handler like `onClick`, `onChange`, `onSelect` or any other HTML DOM events.
```js
import {useState} from "react";
function App(){
const [name, setName] = useState("John");
return(
Hi! my name is {name}.
);
}
```
Note however that the following is the **WRONG** way of using `useState()`. `setEmotion()` will change the value only *after* the rendering is done (or after the return statement):
```js
import { useState } from "react";
function App(){
//We create a state like so
const [emotion, setEmotion] = useState("Sad");
console.log(emotion.value); //emotion is "sad"
setEmotion("Happy");
//Sad does not become "Happy". But this is the wrong way of using setEmotion().
console.log(emotion.value); //Still "Sad"
return (
//It will not print anything. The console will show up with errors.
I am {emotion}
);
}
```
Will lead to:
```
Too many re-renders. React limits the number of renders to prevent an infinite loop.
```
Since `setEmotion()` is called for every rendering on loop, the browser will then complain that it is "re-rendering" too much. From the browser's point of view, this is what it looks like:
```js
function render(){
render();
}
render();
```
Because of this, we need a user event handler to prevent an infinite recursion.
`setEmotion()` is supposed to be called only once every time the button is clicked.
## [useReducer()](https://react.dev/reference/react/useReducer)
`useReducer()` is like `useState()`. But unlike `useState()`, `useReducer()` accepts static logic (represented as a function) as its parameter.
```
const [state, function] = useReducer(reducer, initialState)
```
Unlike having state logics being spread out throughout the code with `useState()`, `useReducer()` helps organize different state logic into its respective methods.
### Usage:
```js
function reducer(state, action) {
return { condition: !state.condition};
}
function App(){
const [checked, toggleChecked] = useReducer(reducer, { condition: false });
return (
);
}
```
Or you can use an arrow function to make the code A LOT more legible.
```js
function App(){
const [checked, toggleChecked] = useReducer((checked) => !checked, false );
return (
);
}
```
## [useEffect()](https://react.dev/reference/react/useEffect)
`useEffect()` is a hook that accepts a function and an optional list.
With `useState()`, you (re-)initialize a component with a state. With `useEffect()`, you can perform side effects like directly fetching or updating the state of a component. It is made to output unpredictable results for the user.
`useEffect()` is made to address the common misuse of `useState()`. However, its intended use is mainly for dealing data with third-party tools like backend servers, browser APIs, and timing functions like `setTimeout()` and `setInterval()`.
In short, if you want an expected outcome, use `useState()`. If you want the webpage to interact with the outside world or expect unexpected results, use `useEffect()`.
If your code does not involve (a)synchronization, you do not need `useEffect()`. More [here](https://react.dev/learn/you-might-not-need-an-effect).
There are three possible usage scenarios:
1. Without a dependency (2nd param). **BAD USAGE**
```js
setEffect( () => {
//1st param: code that runs after *every* render
});
```
2. With an empty list
```js
setEffect( () => {
//1st param: code that runs only on the first render
}, []);
```
3. With a list
```js
setEffect( () => {
//1st param: code that runs on the first render then after any dependency value change
},
//2nd param: A dependency array of states specified. If its values change, the code in the 1st param above will run again.
[...,...,...]);
```
### Usage:
To demonstrate how `useEffect()` looks like without a dependency, We use a `setTimeout()` method:
```js
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
});
return
I've rendered {count} times!
;
```
The rendering does not stop as the dependency does not exist. So we have to add an empty array as our second parameter.
```js
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
}, []);
return
I've rendered {count} times!
;
```
Now it only renders once.
## [useRef()](https://react.dev/reference/react/useRef)
All of the hooks mentioned above will require re-rendering when then their values are changed. `useRef()` however, is the exception.
"ref" is short for reference. It lets you "reference"/remember a value without the need of re-rendering.
```js
const ref = useRef(initialValue)
```
Note however that states and refs are two different things. `useRef()` does not rely on states as states trigger re-rendering when they are changed. A ref is just a plain JavaScript that can store a value that is used for later use.
If we pass 0 to `useRef()`,
```js
const ref = useRef(0);
```
`useRef()` returns an object like so (the browser will "see" this):
```js
{
current: 0 //the value passed to useRef
}
```
"curent" is just an attribute of ref (`ref.current`).
### Usage
Here, we hold the number of times the user clicked on a button. Unlike `useState()`, it does not trigger a re-render when the value is changed.
```js
import { useRef } from 'react';
export default function Counter() {
let ref = useRef(0);
function handleClick() {
ref.current = ref.current + 1;
alert('You clicked '+ref.current+' times!');
}
return (
You clicked me {ref.current} time(s)!
);
}
```
Notice how the value of `ref.current` in the return statement is not updated. Refs do not re-render its components when they are re-rendered. They only serve as a storage space for later use.
This [**table**](https://react.dev/learn/referencing-values-with-refs#differences-between-refs-and-state) from the manual is excellent to distinguish between refs and states apart.
# Fetching Data with Hooks
There is a link to output a user's data on Github. Let's the take the following example:
```
https://api.github.com/users/Garenium
```
This shows a user's Github data respresented as a JSON object. In order to fetch this with React, we use `useEffect()` like so:
```js
import "./App.css";
import { useState, useEffect } from "react";
import { useReducer } from "react";
function App() {
const [data,setData] = useState(null);
useEffect(() => {
fetch(
`https://api.github.com/users/Garenium`
).then((response) => response.json())
.then(setData);
}, []);
if(data) return
{JSON.stringify(data,null,2)}
return (
Data
);
}
export default App;
```
The problem with this code is that it cannot handle three different states:
- When the page is loading
- When the page is finished loading
- When there is a fetch problem
Notice that when the webpage was loading, it was showing "Data" in a blink of an eye instead of the actual JSON object. This is because it is the asynchronous nature of the `useffect` hook. If we were to encounter a Github username that didn't exist, we would see this:
![Output when a Github user doesn't exist](image.png)
It is recommended to create three different states like so:
```js
import "./App.css";
import { useState, useEffect } from "react";
//Create a separate component for extract Github user data after useEffect is
//done
function GithubUser({ name, location, avatar }) {
return (
{name}
{location}
);
}
function App() {
//The three states:
const [data, setData] = useState(null); //Data to load fetch
const [error, setError] = useState(null); //setError when fetching fails
const [loading, setLoading] = useState(false); //setLoading before data is set
useEffect(() => {
setLoading(true);
fetch(
`https://api.github.com/users/moonhighway`
)
.then((response) => response.json())
.then(setData)
.then(() => setLoad(false))
.catch(setError);
}, []);
if(loading) return
Loading...
//Show this when the state is loading
if(error) return
{JSON.stringify(error)}
//When fetching fails. stringify error
if(!data) return null; //return null when there's no data
return (
);
}
export default App;
```