reactjsreact-hooks

when to return [] vs {} when creating a custom hook?


So I am curious to when you should return an array to destructure and when you should return an object to destructure with custom hooks in react because as in many cases, I believe they will give you the same results.

return [name,age]
return {name,age}

Solution

  • The reason for picking one over the other isn't really based on a behavioural difference. It's often (not always, please read this whole post!) because returning an array inverts control of the naming of each item in the return value to the user of the hook, without having to use aliases (due to how the array destructuring syntax is), which would be cumbersome in certain cases (see below).

    Everything will update as normal whether it's an object or array -- it is not relevant to behaviour. It's relevant to just picking the most appropriate structure. And that varies depending on various aspects of the hook and how it will be used.

    Imagine if useState returned an object and you had multiple state items:

    const { state: stateItem1, setState: setStateItem1 } = useState()
    const { state: stateItem2, setState: setStateItem2 } = useState()
    
    

    Much more noise right? By using an array as the return value, we don't need all the object destructuring aliasing. That's why the React authors picked an array return value in this case. They are effectively using an array not for its list-like capabilities, but just because the syntactic sugar on destructuring an array is less noisy.

    However, this doesn't mean you should go and use an array everywhere. It makes less sense the more properties you have as you are then expecting the consumer to understand the order. useState is small enough and well-known enough for this not to be a problem. It also is typically used multiple times in a component, which emphasized the need for nicer aliasing syntax.

    Really, it only makes sense to use [] if you: have a small number of items; the array is fixed width and a well-defined order (e.g. a list of meaningful defined functions/values where the position of each is always the same); and the purpose of the hook is so generic you expect it to be used many times in one component (so they need easy aliasing). This isn't a hard and fast rule, just guidelines.

    Otherwise, use an object with named properties.

    It's also worth noting that using an array introduces lasting constraints moving forward, due to the positional nature of the data therein. When you need to return something extra later on, you can either settle with putting it at the end of the array, or put it elsewhere and accept it's a breaking change, then change places the hook is consumed.

    Everything I said is really about {} vs [] in the context of picking which to use for purposes of destructuring. Of course, if you have an array that is an array because it's the best data structure (e.g. it returns a list of users: [{age: 30, name: 'user1'}, {age: 35, name: 'user2'}]), then this is an overriding factor and you need to return an array. In these cases, the user of the hook wouldn't be destructuring/aliasing from it anyway as it would have variable length and/or meaningless non-guaranteed order.

    Your example is not this case though. A natural shape is an object with different types on each key (string for name and number for age) and those keys also together represent one conceptual item - a single user. It doesn't make sense from a data structure perspective to say they are a "collection".