Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better aproach for destructing Custom React Hooks with multiple returns?

Context:

I saw the documentation of react hooks and all the hooks return two values that are destructed in an array. But what if I have a hooks that returns an array with much more than two, like this:

const [value, someMethod, someMethod2, someMethod3, someMethod4] = useSomeMethod(someValue)

But I only want some of the methods, not all of then. In this case I will need to do something like:

const [value, , , someMethod3, someMethod4] = useSomeMethod(someValue)

And this way, it doesn't look that bad, but imagine if you have a hook that returns more than 10. I will show a real example so it can be more clear.

Real example:

I'm creating a hook for dealing with arrays, so it would be something like:

const useArray = (initialState) => {

    const [array, setArray] = useState(initialState)

    const add = (value) => {
        let newArray = [...array, value]
        setArray(newArray)
    }

    const deleteByIndex = (index) => {
        let newArray = array.filter((x, i) => i != index)
        setArray(newArray)
    }

    const updateByIndex = (value, index) => {
        let newArray = [...array]
        newArray[index] = value
        setArray(newArray)
    }

    return [array, add, deleteByIndex, updateByIndex]
}

and to use this hook, it would be like:

const [bananas, addBananas, deleteBananasByIndex, updateBananasByIndex] = useArray(someBananas)

But if you know a little bit of array manipulation, there is much more than 3 methods, maybe more than 10.

What I want to do is create a hooks for arrays that can handle all types of manipulations for an array and use it anywhere in my project.

The Problem:

The problem comes when I'm going to use this hooks, because all methods aren't going to be use when I call the hook, but all methods are going to be used in the project. And to use only some of the methods, it would be something like this:

const [value, oneMethod, , , someMethod, , otherMethod, , moreMethod] = useSomeMethod(someValue)

I thinks this is very bad because I need to remember the other of the methods and also using alot of , doesn't look good.

I thought of deconstruct it as an object, but than the names would be fixed and also I wouldn't be able to use more that one useArray in a component.

So, taking all of this in consideration...

Is there a better aproach for destructing Custom React Hooks with multiple returns than remembering the order of the returns and using alot of , ?

Observations: My question isn't about arrays, is about destructing the return of a react hook

like image 511
Vencovsky Avatar asked Mar 22 '19 12:03

Vencovsky


2 Answers

Update

As @worc said in the comments, useReducer is a better aproach and also the correct aproach, cases like this are supossed to use useReducer.

Also, here is how it would work:

function arrayReducer(array, action) {
    switch (action.type) {
        case 'push':
            return [...array, action.value]
        case 'deleteByIndex':
            let deleteByIndex = array.filter((x, i) => i != action.index)
            return deleteByIndex
        case 'updateByIndex':
            let updateByIndex = [...array]
            updateByIndex[action.index] = action.value
            return updateByIndex
        default:
            throw new Error()
    }
}

export default function useArray(initialState){
    return useReducer(arrayReducer, initialState)
}

Thanks for everybody that helped!


So the way of doing this is returning an object and renaming all of the variables

const useArray = (initialState) => {

    const [array, setArray] = useState(initialState)

    const add = (value) => {
        let newArray = [...array, value]
        setArray(newArray)
    }

    const deleteByIndex = (index) => {
        let newArray = array.filter((x, i) => i != index)
        setArray(newArray)
    }

    const updateByIndex = (value, index) => {
        let newArray = [...array]
        newArray[index] = value
        setArray(newArray)
    }

    return {array, add, deleteByIndex, updateByIndex}
}


const {
    array: bananas, 
    add: addBananas,
    deleteByIndex: deleteBananasByIndex, 
    updateByIndex: updateBananasByIndex
} = useArray(someBananas)
like image 132
Vencovsky Avatar answered Nov 15 '22 13:11

Vencovsky


You can return an object instead of an array

so,

 return {obj1, obj2, obj3,..} 

and use

const {obj1, obj3} = useHook();
like image 25
Pravinkumar Avatar answered Nov 15 '22 13:11

Pravinkumar