Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
November 10, 2020 02:08 pm GMT

Reducing component complexity with React Hooks

This is my first post here, so go easy on me

Essentially, a hook is just a javascript function prefixed with use which is allowed to invoke other hooks.1 Within reason, you can make a custom hook do whatever you want. Network requests, state management, redirecting the user, invoking other hooks, etc. You can get really creative with them.

Over the past few months, one of my favorite ways to use hooks has been to abstract out complicated component logic.

What do I mean by this?

Imagine you have a Newsfeed component. It loads and renders posts from your api. The simplest implementation is to inline everything at the top of your component:

// Newsfeed.jsximport React, { useState } from 'react'const Newsfeed = () => {  const [loading, setLoading] = useState(false)  const [posts, setPosts] = useState([])  const getPosts = () => {    setLoading(true)    fetch('/v1/posts')      .then(data => data.json())      .then(data => setPosts(data))      .then(() => setLoading(false))  }  return (    <div>      {posts.map((post, index) => (        <div key={index}>          <h1>{post.title}</h1>        </div>      ))}      {loading ? (        <p>Loading...</p>      ) : (        <button onClick={getPosts}>Load Posts</button>      )}    </div>  )}export default Newsfeed
Enter fullscreen mode Exit fullscreen mode

The problem

The above implementation works, but I want you to imagine for a moment that suddenly instead of two states to manage, we have 5. We've got loading, posts, page, perhaps we've got open to track whether or not the user clicked into a post, and even replying to track if they're replying to that post. Instead of just getPosts, we have a bunch of different functions. Say, getPost, getPostComments, postComment, etc.

That's a lot of complexity to add to the top of a functional component. It's an unmaintainable amount of complexity. That isn't even considering how the render portion of that component will grow in complexity, too. Sometimes you can break one complex component into many smaller components, but you can't always cleanly separate the logic.

A solution

Just don't include the functional complexity in the component.

Take all of it, and isolate it into a hook.

Why a hook? Because the integration is easy and seamless. No need to set up reducers or contexts. You get lots of bonuses like being able to call other hooks or automatic rerenders when your state updates.

The most important concept is that our hook, when used like this, must return everything required for the component to render. You can almost think of the return value of the hook as props being passed to the component.2

Let's see what it looks like after we import the hook, destructure the values returned, and ctrl+x and ctrl+v all of the logic away.

// Newsfeed.jsx import React from 'react'import useNewsfeed from './useNewsfeed'const Newsfeed = () => {  // Destructure the value that the hook returns   const {    state: { loading, posts },    getPosts  } = useNewsfeed()  return (    <div>      {posts.map((post, index) => (        <div key={index}>          <h1>{post.title}</h1>        </div>      ))}      {loading ? (        <p>Loading...</p>      ) : (        <button onClick={getPosts}>Load Posts</button>      )}    </div>  )}export default Newsfeed
Enter fullscreen mode Exit fullscreen mode
// useNewsfeed.jsimport { useState } from 'react'export default () => {  // Our hook manages our state for us   const [loading, setLoading] = useState(false)  const [posts, setPosts] = useState([])  // It also manages our functionality  const getPosts = () => {    setLoading(true)    fetch('/v1/posts')      .then(data => data.json())      .then(data => setPosts(data))      .then(() => setLoading(false))  }  // Finally, it exposes only what is required by the component  return {    state: { loading, posts },    getPosts,  }}
Enter fullscreen mode Exit fullscreen mode

Should you do this?

The answer is... it depends. It's like asking if you should inline a styling rule or if you should put it into a stylesheet. There are valid situations for both.

There are a couple of benefits to consider:

  1. It cleanly separates your concerns without adding much complexity.3

  2. It cleans up your imports a lot. You don't have 20 imports from a component library inbetween your network request imports.

  3. Legibility. You can take one glance at the component (or the hook!) and you understand what's going on.

  4. It tends to consolidate logic into one location, which makes locating, understanding, and altering it easier.

  5. Seamless integration. No need to refactor anything.

  6. You can completely forgoe the implementation. Our hook could look like this and our component would be none the wiser:

// useNewsfeed.js// This always returns a fixed value, meaning // the component always behaves as if the posts loaded already.export default () => {  return {    state: {       loading: false,      posts: [{        id: 6,        title: 'Hooks are cool'      }]    },    getPosts: () => null,  }}
Enter fullscreen mode Exit fullscreen mode

Some very important caveats

This doesn't replace the need for separating components into multiple smaller components.

If you choose to do this, you really should be comfortable with how hooks work.

You should also familiarize yourself with how hook dependencies work. For example, if you don't properly use things like useCallback and useMemo, you might end up with infinite loops and not understand why.

If you haven't, I recommend you download an extension that warns you when you're using them incorrectly to spot things like missing hook dependencies.

What do you think?

Do you already use hooks like this?
Do you hate the idea of this?
Do you take it further and create tons of custom hooks?

Lemme know below


1 https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook
2 Similarly, but not exactly the same. Remember, unlike props, React is choosing when to rerender everything based on certain things happening under the hood - like the value of useState or a dependency passed to useCallback changing.
3 With a simple example like our Newsfeed app that only has two states and one function, it probably isn't worth the complexity this adds. It's up to you to decide what's right. Always ask yourself: "Can I quickly develop and maintain a mental model of this?"


Original Link: https://dev.to/crowdozer/reducing-component-complexity-with-react-hooks-202e

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To