Skip to content

React 16.8 Hooks - Part 1 #2

Description

@taystack

React 16.8 Hooks - Part 1

The release of React 16.8 gave us a few extra tools to help optimize render speed and easily maintain state. Specifically, hooks provide a way for React to decide when the DOM needs to be updated.

You might say, "Dude, we have that already." And I would say, "correct, but not like this."

Example task:

  • Create an input UI where we capitalize every word the user inputs.

Let's take a look at a very simple, statefulReact pre 16.8 component.

classExample{constructor(props){super(props);// boilerplate...// initialize the state countthis.state={text: ""};// bind the change methodthis.handleChange=this.handleChange.bind(this);}handleChange(event){consttext=event.target.value.split(" ").map(capitalize).join(" ");setState({ text });}render(){return<><inputonChange={this.handleChange}/>{this.state.text}</>}}

Now, let's take a look at the same component in React 16.8:

First lets make a file called useCapitalizedWords.js and put it in a folder called hooks

// hooks/useCapitalizedWords.jsimport{useEffect,useState}from"react";import{capitalize}from"helpers";exportdefaultfunctionuseCapitalizedWords(){// stateful textconst[text,setText]=useState("");// When text changesuseEffect(()=>{// Update the stored text with capitalized wordssetText(text.split(" ").map(capitalize).join(" "));},[text,setText]);return[text,setText,text.split(" ")];}

Now all we have to do is use our hook.

// Example.jsimportuseCapitalizedWordsfrom"hooks/useCapitalizedWords";functionExample(){// [ "", (function setter), [] ]const[text,setText,words]=useCapitalizedWords();return(<><inputonChange={event=>setText(event.target.value)}/>{words.map(word=><divkey={word}>{word}</div>)}</>);}

I don't know about you, but I would rather maintain that last example. A simple stateful component should look as simple as it is. That was too easy. Lets try something a bit more difficult.

Example task 2 - async hook

Let's make a UI component that grabs my github avatar. We start with a fresh hook useGithubAvatar.

// hooks/useGithubAvatar.jsfunctionuseGithubAvatar(username="taystack"){// Store the urlconst[url,setUrl]=useState("");// Good UI always knows when a resource is loadingconst[loading,setLoading]=useState(false);// When username changes...useEffect(()=>{// Have an async method in scope of the effectasyncfunctiongetUser(username){setLoading(true);// Update loading boolean// Get the userconstuserResponse=awaitfetch(`https://api.github.com/users/${username}`);/* You can change the next lines to: const user = awaitUserResponse.json(); <- just capture the entire user setUser(user); <- change [url, setUrl] = useState("") to [user, setUser] = useState({}); I would also recommend changing the name of the hook to "useGithubUser" */const{ avatar_url }=awaituserResponse.json();setUrl(avatar_url);// Update returned URL stringsetLoading(false);// Update loading boolean }getUser(username);},[username,setUrl,setLoading]);// bind our dependenciesreturn[loading,url];// return the items we need from this hook}

Now when I want to get an avatar url for a user, I just invoke my custom hook! This component below will begin to appear after 100ms and gradually transition opacity over the next 100ms.

constGithubAvatar=({ username, ...props})=>{const[loading,src]=useGithubAvatar(username);return(<img{...props}src={src}style={{opacity: loading ? 0 : 1,transition: "opacity 100ms 100ms", ...props.style}}/>);}GithubAvatar.defaultProps={username: "taystack"};

I'm leaving it here for React 16.8 Hooks Part 1

If you have any questions or complaints about the code I wrote, please leave a comment below.

I hope to inspire you into writing your own hooks. Hooks contribute to functional-style programming, which is a good thing. Like the example above shows, <GithubAvatar /> has one job - show the avatar. Even without props.username it knows what to do, explicitly. Same goes for useGithubAvatar. You can expect that hook to return an array of [bool, string]. I will create an exercise on try {} catch() {} for this hook in a later post.

Functional programming techniques like hooks allow developers to separate concerns of the view (rendered material), and the logic of how to get there. When modularized concerns are clearly defined, functional logic becomes much easier to maintain, debug, and contribute to.

Metadata

Metadata

Assignees

Labels

BlogExperimental blog formatFront endFront end engineering relatedJavaScriptJavaScript related contentReact 16.8+React v16.8+ content included

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions