DEV Community

Allen Shin
Allen Shin

Posted on

React Hooks

Taking a bit of a break from CSS, this week, I've started learning about React hooks. I've heard this topic by name a lot, but I finally ran across the topic in the React Udemy course by Stepehn Girder, and I found that the topic was actually a very familiar one.

React Hooks are basically just another way to declare and work with state in a React component. Normally, state will be declared by a this.state declaration with the constructor function, which contains the variable for your state and the value that you assigned it. You can then use a this.setState function to assign a new value to your state variable in various functions in the component. Hooks in React components basically the same thing, except with one major difference. Hooks can only be used in functional components, and the this.state way of declaring state can only be used in class components.

They also have different syntax and are functions imported from the React library. You can declare them in an object, for ease of use like so.

Alt Text

The ones listed here, useState, useEffect, useRef, are the most fundamental ones that I will go over today. The examples that I was working on were for a dropdown menu widget, which kept track of the selected option, whether the menu was open, and handling a closing of the menu when you clicked outside the menu. The details aren't too important to understand the hooks methods.

useState

As the name of the function says, this is the function that allows you to use state. This function allows you to declare your state variable, your specific state setting function for the variable, and the initialized value for the state. Here's an example of the use of useState.

Alt Text

The array is used to declare the variables in the array that the useState function generates, and the first one represents the state name, and the second one represents the setState function. The value that is inside the parantheses in the useState function is the intialized variable. Just like that, you have declared state!

You can use both the open and setOpen variables wherever you in your function, without have to declare this.state and this.setState everytime. Less typing is always good. However, the downside to hooks is that you have to declare a new useState function everytime you use a new state variable. So, if you wanted to declare another state variable, you would have to give that variable a unique name and setState function with useState.

useEffect

Now you have your state, but what if you wanted to write some component lifecycle methods? For that there is useEffect. With useEffect the syntax for declaring it involves putting a callback function within the useEffect() parantheses, and declaring a second variable which is associated with the type of lifecycle method you want to create. Here's what that looks like in the problem that I was working on.

Alt Text

There are 3 main parts to this useEffect function. The first is the main portion of the function, which is essentially the 'effect', or what happens when this function is triggered. Here I declared that is a callback function checking whether the ref contains the event's target and then attached that to the document's body. This is happens everytime this function is run.

Now the second crucial part is actual a very small portion of the function but it determines, when this function is triggered. That variable is the little array after the comma at the end of the function. Just like componentDidMount and componentDidUpdate are not the same functions, this variable determines when this variable is supposed to be called.

There are basically three options you can put into this variable. 1) [] - an array here means that this effect happens everytime you initalize your component. It makes this function similar to a componentDidMount. 2) 'nothing' - if you leave this field empty, the useEffect function triggers whenever you initialize your component, or whenever it is rerendered (due to something like a state change). 3) [open] - an array with variables inside means this function triggers on initialization as well as whenever any of the variables inside change. The variables in this case are going to be the state variables that you declared with useState.
If those specific state variables you declared in the array aren't changed, this useEffect won't trigger.

The last part of this function is returned function at the end, which is analogous to the componentWillUnmount function. This is used anytime you need to cleanup the triggered effect. This returned function will trigger either 1) whenever the component is unmounted or 2) right before this effect is retriggered. In our case, we needed it to remove the event listener we added when the component was mounted, because a certain error which involved refs that didn't exist.

useRef

Before we dive into the function, we should understand what refs are first. Refs are basically a way for you to "reference" an HTML element directly on the DOM if you needed to refer to it in your component code. Your reference is a variable that you create using the useRef function, which you then give it as a value it to the ref attribute of the HTML element that you would want to connect it to. Let's just take a look at the code, because explaining that was unnecessarily complicated.

First, you declare your ref variable using useRef.

Alt Text

Then you add that variable to the ref attribute of the HTML element you want to reference.

Alt Text

Now whenever you use the ref variable, you are referring to that div with the 'ui form' class directly from the DOM. This is very powerful, because especially with things like eventListeners, you will need to create functions that detect things like where a page was clicked on the DOM that doesn't relate to the component itself. In our case, our component had to create an eventListener that detected whether our component or outside the component was clicked. We couldn't do this without creating a reference to the component itself to see whether the click event's target was inside the component reference.

Hooks are cool

I used to shy away from using functional components because I never knew if I would need to use state, but having discovered hooks, I'm starting to reconsider. There's a lot of cool hook functions (many which I didn't cover), which can give your functional component a lot of the same features that a normal class component. A lot of the syntax can be simpler and easy to pick up. I'm hooked! (sorry)

Top comments (0)