Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning array of functions from custom react hook?

I have a custom react hook:

    function useItem(id) {

        const [value, setValue] = useState();

        useEffect(() => {
            databaseRead(id).then(i => setValue(i));
        }, [id]);

        function setItem(i) {
            setValue(i);
        }

        function writeItem(i) {
            databaseWrite(id, i);
        }

    return [value, setItem, writeItem];
}

When using a hook like this in a component, the returned writeItem function changes every time the value changes (presumably because I create a new array every time).

How can I avoid re-renders of the Button component when I use my hook in an Item like so?

function Item(props) {
    const [item, setItem, writeItem] = useItem(props.id);
    return(
        <>
            <ItemEditor data={item} setItem={setItem}/>
            <Button onPress={writeItem}/>
        </>
    )
}

My current working but awkward approach is to return a useRef object instead of the array from my hook:

function useItem(id) {
    const retVal = useRef({
       value: value, 
       setItem: setItem, 
       writeItem: writeItem
    }).current;

    const [dirty, setDirty] = useState();
    function makeDirty() { setDirty(Math.random()); }

    //and instead of setValue(i) do retVal.value=i; makeDirty();
    return retVal;
}

Many thanks!

like image 430
Staffan_K Avatar asked May 05 '20 15:05

Staffan_K


People also ask

Can a custom hook return a function?

In addition, the custom hook returns the state and the functions to update the state in an array.

Should custom hooks return array or object?

If we are going to be using multiple instances of a hook in a single component, then use array return. If our component will only have 1 (or few instances) of a hook, use object return. That's it!

Can custom hooks return components?

Inspired by the concept of “partial application”, we can try to return a component with props that have been partially bound from a custom hook. However, the naive implementation will return new component definition when bound props changed, and that leads to unmount-remount behaviour that we may not expect.

How do you set an array in React hooks?

By mastering the wrapper function, I finally solved my problem of how to add to an array in React state in three easy steps: Use useState([]) Hook to set state to [] and get state setter function. Pass wrapper function to state setter function (as a call-back function) Update array using .

What is the use of return array in react hook?

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.

How to return multiple values from a function in react?

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. const [one, two] = useNumbers() const { a, b, c } = useAlphabet() So why use one method over another?

How do I get Started with hooks in react?

Let’s get started. A custom Hook is a JavaScript function that begins with use. It is not mandatory to begin the custom Hook name with “use,” but without it, React would be unable to check for violations of the Hooks rules automatically. Therefore, it is critical to adhere to that naming convention.

When to return an object from a hook?

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. A hook that has a more specialized use case and returns a larger number of values may benefit by returning an object.


1 Answers

You can make use of useCallback hook to memoize the functions so that they aren't created again on each render

function useItem(id) {

        const [value, setValue] = useState();

        useEffect(() => {
            databaseRead(id).then(i => setValue(i));
        }, [id]);

        const setItem = useCallback(function(i) {
            setValue(i);
        }, []);

        const writeItem = useCallback(function(i) {
            databaseWrite(id, i);
        }, [id]) // this depends on id, and need to be recreated on id change

    return [value, setItem, writeItem];
}
like image 101
Shubham Khatri Avatar answered Oct 22 '22 13:10

Shubham Khatri