React Hooks

But what is a Hook?

These cases are very common and include animations, form handling, connecting to external data sources, and many other things we want to do from our components. When we try to solve these use cases with components alone, we usually end up with:

  • Huge components that are hard to refactor and test.
  • Duplicated logic between different components and lifecycle methods.
  • Complex patterns like render props and higher-order components.

We think Hooks are our best shot at solving all of these problems. Hooks let us organise the logic inside a component into reusable isolated units.

React provides a few built-in Hooks like useState. You can also create your own Hooks to reuse stateful behaviour between different components. We’ll look at the built-in Hooks first.

What was wrong with class components?

Unfortunately, the lack of side effects makes these stateless components a bit limited, and in the end, something somewhere must manipulate state. In React, this generally meant that side effects are added to stateful class components. These class components, often called container components, execute the side effects and pass props down to these pure stateless component functions.

One of the biggest complaints is that you often have to repeat logic in componentDidMount and componentDidUpdate.

async componentDidMount() {
const response = await get(`/users`);
this.setState({ users: response.data });
};
async componentDidUpdate(prevProps) {
if (prevProps.resource !== this.props.resource) {
const response = await get(`/users`);
this.setState({ users: response.data });
}
};

With Hooks, this side effect code can be handled in one place using the effect Hook.

A class example:

import React, { Component } from "react";

export default class Button extends Component {
state = { buttonText: "Click me, please" };

handleClick = () => {
this.setState(() => {
return { buttonText: "Thanks, been clicked!" };
});
};

render() {
const { buttonText } = this.state;
return <button onClick={this.handleClick}>{buttonText}</button>;
}
}

The example above using hooks:

import React, { useState } from "react";

export default function Button() {
const [buttonText, setButtonText] = useState("Click me, please");

function handleClick() {
return setButtonText("Thanks, been clicked!");
}

return <button onClick={handleClick}>{buttonText}</button>;
}

Effect Hook
You’ve likely performed data fetching, subscriptions, or manually changing the DOM from React components before. We call these operations “side effects” (or “effects” for short) because they can affect other components and can’t be done during rendering.

The Effect Hook, useEffect, adds the ability to perform side effects from a function component. It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes, but unified into a single API.

What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.

Effect Hook with cleanup

import React, { useState, useEffect } from 'react';function FriendStatus(id) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribe(id, handleStatusChange); return function cleanup() {
ChatAPI.unsubscribe(id, handleStatusChange);
};

});

return(
if (isOnline === null) 'Loading...';
else isOnline ? 'Online' : 'Offline';
);
}

Why is useEffect called inside a component? Placing useEffect inside the component lets us access the count state variable (or any props) right from the effect. We don’t need a special API to read it — it’s already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.

Does useEffect run after every render? Yes! By default, it runs both after the first render and after every update. Instead of thinking in terms of “mounting” and “updating”, you might find it easier to think that effects happen “after render”. React guarantees the DOM has been updated by the time it runs the effects.

Context Hook

import React, { useContext } from 'react';
const TestContext = React.createContext();function Display() {
const value = useContext(TestContext);
return <div>{value}, I am learning react hooks.</div>;
}function App() {
return (
<TestContext.Provider value={"Hey"}>
<Display />
</TestContext.Provider>
);
}

Ref Hook

import React, { useRef } from 'react';function App() {
const inputElement = useRef(null);
const onButtonClick = () => {
inputElement.current.focus();
};
return (
<>
<input ref={inputElement} type="text" />
<button onClick={onButtonClick}>Focus to input</button>
</>
);
}

Reducer Hook

import React, { useReducer } from 'react';
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'inc': return { count: state.count + 1 };
case 'decs': return { count: state.count - 1 };
default: throw new Error();
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
<h2>Count: {state.count}</h2>
<button onClick={() => dispatch({type: 'inc'})}>+</button>
<button onClick={() => dispatch({type: 'decs'})}>-</button>
</>
);
}

Thanks for reading!

More Useful Resources:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store