Write a Custom State Hook in React

Joe Previte
InstructorJoe Previte
Share this video with your friends

Social Share Links

Send Tweet
Published 5 years ago
Updated 3 years ago

Writing your own custom State Hook is not as a daunting as you think. To keep things simple, we'll refactor our text state value that uses useState and instead create a custom hook called useText.

Instructor: [0:00] Starting where we left off in the previous video in feedback.effect.js, we're going to copy everything, create a new file called feedback.custom.js and paste that in. To write our first custom State Hook, all we're going to do is be refactoring this part of our code.

[0:19] Remember, we're using one piece of state right now called text, and we have a function called setText which allows us to update that value. Up near our import statements, we're going to add a function called useText. We're calling our custom state hook useText because we're following the pattern presented by React.

[0:40] We have useState, useEffect, all of the other Hooks start with use. That's how you know that it's this custom hook. Our function is going to take an initial value, then we'll define the function block. Here, all we're going to do is cut this and paste it here. We're going to change our empty string to the initial value that's passed in when calling our function.

[1:06] Then we're going to return an array of text and setText. We're going to leave this as it is right now. We'll come back and refactor in a second. To use it, we're going to go back inside of our component and call it just like we did before with our array destructuring, but instead of calling useState, we're going to call useText because that's the name of our custom state hook.

[1:28] For initial value, we're going to pass in an empty string. You can see this looks almost identical to the useState call we had earlier. Remember we're doing array destructuring. We are taking two elements. The first element we're naming "texts." That'll be our value. The second element we're naming "setText." All is the same here.

[1:48] Now we're going to make two changes. We're going to call this feedback "custom component," and then we're going to go towards the bottom and change the title to "custom example." Then we'll go into app and import our new component. Now if we go into the browser, we'll see our custom example.

[2:05] If we take a look, let's try typing and submitting. If it works, we should see "Hello." It's still working using our custom hook. Let's head back and let's clean this up a bit. We know that useState returns an array containing two elements, the state value and the function to update it. We're destructuring it as text and setText.

[2:31] Instead of destructuring it and then returning a new array with those two values, let's just return this useState call. Because again, we know what it's returning so we return that in our custom hook, and then when we call it, we do the destructuring there. Let's go back to the browser and verify this works. You'll notice two things.

[2:52] One, we have a new warning from React. React hook useEffect has a missing dependency setText. Let's fix that real quick. setText no longer comes from useState but it comes from our custom hook. Because of that, React isn't really sure what it is and since we're using it inside of our useEffect, it wants us to add it as a dependency just in case it changes.

[3:17] We'll go ahead and add that in and if we clear the console and refresh, we no longer have that warning and our useEffect is still working. Now let's verify that the text and setText is still working. Cool. It's still working. As you can see, that's how you write a custom state hook.

Ben Suen
Ben Suen
~ 4 years ago

Why the dependency [setText] is used instead of [text] ?

Joe Previte
Joe Previteinstructor
~ 4 years ago

Why the dependency [setText] is used instead of [text] ?

Great question, Ben!

If we take a look at our useEffect, you'll notice we're using setText in the callback function, but not using text.

useEffect(() => {
    async function getStarWarsQuote() {
      // Get initial text
      const response = await fetch(
        'https://starwars-quote-proxy-gi0d3x1lz.now.sh/api/randomQuote'
      )
      const data = await response.json()
      const quote = data.starWarsQuote
      setText(quote)
    }
    getStarWarsQuote()
  }, [setText])

We only need to pass dependencies that are used within the callback function. I hope that clarifies the reasoning.

Ben Suen
Ben Suen
~ 4 years ago

setText is a function, when will the dependency happen? Once setText is called? Or once the reference of setText is changed?

Joe Previte
Joe Previteinstructor
~ 4 years ago

setText is a function, when will the dependency happen? Once setText is called? Or once the reference of setText is changed?

Yes, you're right. It is a function. The dependency would "change" if the reference to setText somehow changed. Exactly!

Yannis
Yannis
~ 4 years ago

Why would it be a benefit to create custom hooks ?

Joe Previte
Joe Previteinstructor
~ 4 years ago

Same reason you might create a function or a component - reusability, better abrastraction, extracting it to share in the open source community.

Here's a great example from @dayhaysoos who used this course to create a custom hook called use-stripe-cart

Yannis
Yannis
~ 4 years ago

Thank your for the answer

Markdown supported.
Become a member to join the discussionEnroll Today