DEV Community

Ian Jones
Ian Jones

Posted on

Should hooks always return an array?

Looking at gatsby's useStaticQuery, it just returns an object where I would expect it to return an array. I've been using urqls useQuery lately and it returns and array with the result in the first spot of the array.

Is this just a preference or should this be a convention our libraries should follow?

Oldest comments (3)

Collapse
 
camilomejia profile image
Camilo Mejía

I don't know about Gatsby (just learning), but hooks could return anything, not just arrays. Looking at the build in React hooks, the arrays format is used in useState and useReducer, but useContext for example return an object and useEffect return nothing. In your custom hooks, you could return anything, so theoretically, any hook in Gatsby could return what they want, not only arrays.

Collapse
 
dance2die profile image
Sung M. Kim

Generally when you create your hooks, you can return anything (array, object, symbol, etc).

Even in React documentation, useFriendStatus returns a boolean value.

import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}
Enter fullscreen mode Exit fullscreen mode

The reason you see many hooks returning an array is to provide a way to a hook consumer to name the state & the state mutator the way you want.

JavaScript array destructuring syntax allows you to name each element.

When you return an object, you are forced to either use the object property name or need to alias it.

e.g.)

function useCustomState() {
  // logic ...
  return {state, setState};
}

function App() {
  const {state, setState} = useCustomState();
  // or you need to alias it to fit your business logic
  const {state: price, setState: setPrice} = useCustomState();
}
Enter fullscreen mode Exit fullscreen mode

useState, useReducer and the ones you mentioned are so generic, so returning an object would put burden of such redundant aliasing as shown above.

IHMO, So it's a matter of a preference on how you want to consumer to consume your hooks.

Collapse
 
georgenorris profile image
George C. Norris

No you don't have to return a value. You can have a custom hook call useEffect and do some clean up. It doesn't have to return anything.