The React Library
React is a JavaScript library used for building user interfaces. The library comes pre-built with lots of awesome features that allow for creating interactive and high-performance web applications.
In this article, I will be going through some hooks that are built into React. Not to be misconstrued with a right hook from boxing🥊, a hook is simply a function that handles some operation for the user interface. For your reference, here is the React official documentation or the reference manual.
1. Use State Hook
Unlike JavaScript, React has a virtual DOM which affords us the freedom to create a state within the browser. This erases the need to access HTML DOM elements the traditional way in the JavaScript file. For example in plain JavaScript, one would have to write something like this:
let submitButton = document.getElementById("btn");
submitButton.addEventListener("click", function);
However, since React uses components, we can define the logic that determines what gets rendered in the browser. The useState hook returns a stateful value, and a function to update it. We can write it like this:
import { useState, React } from "react";
const Hooks = () => {
let [counter, setCounter] = useState(0);
return (
<div>
<p>{counter}</p>
<button onClick={() => setCounter((counter += 1))}>Click</button>
</div>
);
};
export default Hooks;
We have to use a destructured assignment for our counter variable where the first value (counter) is a stateful value equal to 0 (value in brackets) and the second value (setCounter) is a function that updates the variable.
Notice how I've declared my variable using the let keyword. This is to avoid a Type Error which prohibits reassignment of the variable if we had declared it using the const keyword.
Right hook punch:
2. Use Effect Hook
This hook accepts a function that contains imperative, possibly effectful code. It is commonly used to feed a React application with data from an API endpoint.
The useEffect function accepts 2 mandatory parameters. The first is an imperative function that can return a cleanup function. The second should be an array or undefined. If present, the effect will only activate if the values in the list change.
To utilize the useEffect hook we first import the module:
import { useEffect, useState } from "react";
For this specific example, create a state variable that stores a reference to the data and a URL variable that points to an active API endpoint:
const [data, setData] = useState(null);
const url = "https://jsonplaceholder.typicode.com/comments";
Then, we should call the useState hook as a chained Promise function:
useEffect(() => {
fetch(url).then((res) => {
if (!res.ok) {
throw Error("Could not fetch the data for that resource.");
}
return res.json();
}).then((data) => {
setData(data);
}).catch((err) => {
console.error(error);
});
}, [url]);
I have another article about JavaScript Promises to explain the concept of the Promise object. The return statement of the component can then be rendered this way:
return (
<div>
{data}
</div>
)
Right hook punch:
3. Use Ref
The useRef hook returns a mutable ref object whose current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
The useRef() hook is useful for more than the ref attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.
Suppose we wanted to create a newsletter prompt. We can start by importing the useRef hook:
import {React, useRef, useEffect, useState} from 'react';
Then create an object that will serve as the default state:
const modalData = {
email: '',
frequency: 'weekly'
}
Then create a React component that has four props:
const NewsLetterModal = ({ onSubmit, isOpen, onClose, hasCloseBtn }) => {
const focusInputRef = useRef(null); // Creating a reference to the input element
const [formState, setFormState] = useState(modalData);
const [isModalOpen, setModalOpen] = useState(isOpen);
const modalRef = useRef(null);
useEffect(() => {
if(isOpen && focusInputRef.current){
setTimeout(() => {
focusInputRef.current.focus();
}, 0);
}
}, [isOpen]);
const handleInputChange = (event) => {
const {name, value} = event.target;
setFormState((previous) => ({
...previous,
[name]: value
}));
};
const handleSubmit = (event) => {
event.preventDefault();
onSubmit(formState);
setFormState(modalData);
};
const handleCloseModal = () => {
if(onClose){
onClose();
}
setModalOpen(false);
}
const handleKeyDown = (event) => {
if(event.key === "Escape"){
handleCloseModal();
}
};
useEffect(() => {
setModalOpen(isOpen);
}, [isOpen]);
useEffect(() => {
const modalElement = modalRef.current;
if(modalElement){
if(isModalOpen){
modalElement.showModal();
} else {
modalElement.close();
}
}
}, [isModalOpen]);
The return statement should be the HTML5 dialogue element that contains a form element with an email input field and a submit button.
return (
<dialog ref={modalRef} onKeyDown={handleKeyDown}>
{hasCloseBtn && (
<button onClick={handleCloseModal}>Close</button>
)}
<form onSubmit={handleSubmit}>
<div>
<label>Email</label>
<input
ref={focusInputRef}
type="email"
id="email"
value={formState.email}
onChange={handleInputChange}
required
/>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
</dialog>
)
}
Right hook punch:
4. Use Reducer
This is an alternative to useState. The useReducer hook is usually preferable to useState when you have complex state logic that involves multiple sub-values. It also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks.
To use it, firstly we import the useReducer module:
import { useReducer, React } from "react";
Then, we create a variable that is equal to the useReducer hook. The useReducer function accepts 2 parameters; a reducer
function and an object:
const [current, dispatch] = useReducer(reducer, {
count: 0,
displayText: true,
});
The return statement of the component should render those values and call the dispatch function after an event:
return (
<div>
<p>{current.count}</p>
<p>{current.displayText && "Hello World"}</p>
<button onClick={() => dispatch({ type: "add" })}>Add</button>
<button onClick={() => dispatch({ type: "text" })}>Words</button>
</div>
);
Lastly, we need to define the reducer function which is passed into the dispatch method that we defined:
const reducer = (state, action) => {
switch (action.type) {
case "add":
return { count: state.count + 1, displayText: state.displayText };
break;
case "text":
return { count: state.count, displayText: !state.displayText };
break;
default:
return state;
}
};
Notice how the return value for the switch case of 'add' is different from the return statement of the switch case of 'text'.
Essentially, clicking the button that says "Words" uses a Boolean
value to toggle the rendering of the "Hello World" text. While the "Add" button increments the value of the count variable.
Right hook punch:
5. Use Layout Effect
The function signature of useLayoutEffect is identical to useEffect, but it fires 🔥 synchronously after all DOM mutations. It is used to read the layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously before the browser has a chance to paint🎨. Preference should be given to the standard useEffect when possible to avoid blocking visual updates. If you’re migrating code from a class component, useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate.
For our use case, the first step is to import the module from React together with useRef
.
import { useLayoutEffect, useRef, React } from "react";
Then, inside the React component, define a variable that is equal to useRef(null)
and then call the useLayoutEffect function.
const textRef = useRef(null);
useLayoutEffect(() => {
alert(textRef.current.value);
}, []);
Lastly, we can return an HTML input element that references the textRef variable.
return <div>
<input ref={textRef} type="text" value="Candy🍭" />
</div>;
Right hook punch:
Conclusion
React is my favorite JavaScript library because it is open-source🆓, maintained by seasoned software engineers😎, and has widespread access to support resources🌐. The concepts I have covered in this article may exist in other JavaScript frameworks but might be implemented differently. React powers many of the websites that we use daily⚡. One way to identify a React application is by noticing how quickly it renders stuff in the browser🏃. I encourage you to do some further research on the React topics listed below.
- useMemo
- useImperativeHandle
- createContext
Let me know your thoughts in the contact section😉. Until the next article, happy coding🧑💻!