Writing Your Own React Hooks, the Return Value
Tags: react, javascript, webdev, tutorial
Published: 2019-12-19 11:35:11

JavaScript can only return one value from a function.  However, destructuring in modern JavaScript makes this largely irrelevant.

We can return multiple values in arrays or objects from a function and instantly destructure them.  And, as you know, a React hook is just a convention-following function.

```react
const [one, two] = useNumbers()
const { a, b, c } = useAlphabet()
```

_**So why use one method over another?**_

Let's look at some different use cases and explore why we might want to return an array vs. an object.

First, it should be noted, that we don't have to return anything.  The built in `React.useEffect` hook does just this, (returning `undefined` actually).

We can also just return a single value, such as a string or integer.  An example of this might be a hook that subscribes to a WebSocket API and returns a continuously updating value representing the current number of users online:

```react
function OnlineUsers() {
  const userCount = useOnlineUserCount()

  return (
    <Users count={userCount} />
  )
}
```

---

## Returning an Array

A hook that has a very general use case benefits from exporting return values as an array. A great example of this is actually the built-in `React.useState` hook. Exporting an array makes it easy to customize the names of the state variables and their setters.  Unique names enable us to use the hook repeatedly.

```react
const [color, setColor] = useState('MintCream')
const [width, setWidth] = useState('100vw')
```

A slightly-contrived example of a custom hook that would benefit from returning an array might be CSS builder that also holds on to some state.

```react
const [leftStyle, setLeftTheme] = useStyleBuilder('dank-kitty')
const [rightStyle, setRightTheme] = useStyleBuilder('no-drama-llama')
```

### When to Return an Array

- _**The number of values that need to be returned is low.**_  Order is significant and remembering the order of a bunch of values takes extra brain cycles.

- _**The hook is expected to be used more than once in the same component.**_  Although we can rename properties when destructuring an object, the simpler syntax for custom-named values returned from an array makes more sense.

---

## Returning an Object

A hook that has a more specialized use case and returns a larger number of values may benefit by returning an object. 

Object destructuring doesn't rely on ordering and it is easier to ignore values that are not needed. An example might be a hook with 3 or 4 state values along with handler functions:

```react
const { color, count, isValid, handleChangeColor, handleChangeCount } = useItemOptions()
```

### When to Return an Object

- _**The number of values that need to be returned is high.**_  We don't have to remember the order or even use all the values when returning an object.

- _**The hook is not expected to be used more than once in the same component.**_  We can use the original property names when destructuring an object returned from a hook that will only be used once in a component.

---

## Not destructuring

If a hook needs to return a larger number of values _AND_ is expected to be used more than once, we don't have to destructure at all.  This can occasionally be useful.

```react
  const leftOptions = useItemOptions()
  const rightOptions = useItemOptions()

  return (
    <>
      <Column
        side="left"
        color={leftOptions.color}
        count={leftOptions.count}
        isValid={leftOptions.isValid}
        handleChangeColor={leftOptions.handleChangeColor}
        handleChangeCount={leftOptions.handleChangeCount}
      />
      <Column
        side="right"
        color={rightOptions.color}
        count={rightOptions.count}
        isValid={rightOptions.isValid}
        handleChangeColor={rightOptions.handleChangeColor}
        handleChangeCount={rightOptions.handleChangeCount}
      />
    </>
  )
```

---

## Not Destructuring with Spread

If we are careful with the naming of the properties in the object that our hook returns, we can use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to dump props directly into our components.

The above component could be rewritten using the spread syntax like this:

```react
  const leftOptions = useItemOptions()
  const rightOptions = useItemOptions()

  return (
    <>
      <Column side="left" {...leftOptions} />
      <Column side="right" {...rightOptions} />
    </>
  )
```

_(Apparently, Dev.to syntax highlighting for the spread operator in JSX is not yet supported, but this works.)_

--- 

## Conclusion

We can return multiple values in several different ways that make sense at different times.  Hopefully, this will give you some ideas about how to make your hooks more readable and easier to understand.

We have a bunch of options in our toolbelt here.  There is overlap and there are trade-offs, so play around and figure out what makes sense for your application. And have fun!