DEV Community

Cover image for Understanding React Hooks
JerryMcDonald
JerryMcDonald

Posted on • Edited on

Understanding React Hooks

React Hooks are a feature that is new to react since the React 16.8 update. They give you the ability to use state features without creating a class constructor. Hooks allow developers to break up complex class constructors even further. Developers wanted an easier way to break down substantial class components, extract stateful components to function or another element, and cut down on intricate patterns like props and higher-order components. Hooks solved the problem of React functions not having "state" in them.

According to the React documentation on hooks, the company has no plans to eliminate the class component. The React team would like developers to gradually adapt hooks and combine the knowledge with React skills they already know. I am going to talk about some hooks you should know to get started. But before we do, let us look at some of the rules you need to follow while using hooks.

Rules of hooks

  1. You only want to call hooks at the top level of your function. Do not use useState in a loop, conditional, or nested function. Because for React to keep track of your hooks, they need to be called in the same order each time your functional component runs.

  2. You only want to call hooks from React Functional Components. You will need these inside a class component or outside of a component.

  3. When you learn enough to create custom hooks. The names of your hooks must start with 'use.'

Let's take a look at the two hooks you already have access to in your React application. useState and useEffect.

State Hook

The first hook I will talk about is 'useState,' designed to hold a small-ish amount of data in a function components state. The great thing about 'useState' is that you can assign any data type you would like. You can useState with an array, an object, a number, a string, or a boolean. Each useState call will create a new single piece of state.

Let look at an example of a state variable that I would like to call visible. I would also like to change the value of visible at any point in my functional component.

  // Create a piece of state, and initialize it to `true`
  // `visible` will hold the current value of the state,
  const [visible, setVisible] = useState(true);
Enter fullscreen mode Exit fullscreen mode

In the above example, we can see that useState is returning an array of two components. A visible element that will hold the state's value and a setVisible function that will change the value of the state.

function Profile() {
  const [visible, setVisible] = useState(true);

  function toggleVisibility() {
    setVisible(!visible);
  }
Enter fullscreen mode Exit fullscreen mode

But what if we need another way to do the functionality above but by using an updater function. Using prevState can be useful if you are updating your state inside of a closure. The below example will have the same outcome as above.

function Profile() {
  const [visible, setVisible] = useState(true);

  function toggleVisibility() {
    setVisible(prevState => !prevState);
  }
Enter fullscreen mode Exit fullscreen mode

We can also save arrays and objects to our state.

// array example
const [someArray, setSomeArray] = React.useState([]);

setSomeArray(prevState => [...prevState, 'newdata'] );
Enter fullscreen mode Exit fullscreen mode

You can see here when we are setting a new value to the state array; we utilize the ES6 spread operator to concatenate the prevState array with our new data.

Let's look at setting an object to state and using the spread operator to update it.

function Profile() {
  const [user, setUser] = useState({
    username: '',
    profileImgUrl: ''
   });

  const updateUrl = url => {
    setUser({
      ...user,
      profileImgUrl: url
    });
  };
Enter fullscreen mode Exit fullscreen mode

An important thing to remember is that you cannot update a state by reassigning the state name. Suppose you find yourself having a nested array or object and having trouble using the spread operator, concat, and update a single element in your object. You do a trick that I like to use and create a new object before updating the state.

function Profile() {
  const [user, setUser] = useState({
    username: '', 
    password: '',
    pets: ['Ms.Mittens', 'JoJo'],
    }

  const addAPet = petName => {
    // make a copy of the user
    const userCopy = { ...user }
    // now you can make changes to the copy
    userCopy.pets.push(petName);
    // then you can set the state to the new object
    setUser(userCopy);
  };
Enter fullscreen mode Exit fullscreen mode

Learning the trick can come in handy when your objects become a bit more complicated and you can't get the spread operator to work quite right.

Effect Hook

The Effect hook useEffect allows the developer to perform side effects from a functional component. These side effects can include but are not limited to data fetching and subscriptions.

The useEffect hook can be considered a componentDidMount or a componentDidUpdate from a class component.

function MemberPage() {
  const [memberCount, setMemberCount] = useState(0);

  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You have ${memberCount} members`;
  });

  return (
    <div>
      <p>You have ${memberCount} members</p>
      <button onClick={() => setMemberCount(prevState => prevState + 1)}>
        Add a member
      </button>
    </div>
Enter fullscreen mode Exit fullscreen mode

By default, React is running the useEffect each render, including the first render, making the useEffect useful for a fetch request at the beginning of your components life cycle.

  useEffect(() => {
    fetch(
      `https://api.github.com...`,
      {
        method: "GET",
        headers: ..."
        })
      }
    )
      .then(res => res.json())
      .catch(error => console.log(error));
  });
Enter fullscreen mode Exit fullscreen mode

Using the useEffect Hook will allow you to affect other components and do important data collection that cannot be done during rendering.

Using Hooks can allow you to separate your class components even further, which will make your code easier to read and debug. If you are new to using hooks and would like to learn more about them (or even how to create hooks), I put some excellent resources down below.

Resources:

  1. React docs hooks-intro
  2. Making sense of React Hooks
  3. Banner designed on Canva
  4. rules-of-hooks
  5. Making API calls with React Hooks

Top comments (0)