React onClick callAll functions syntax

Viewed 127

I recently started to learn React in more depth, and something is triggering me because I cant understand this syntax (I know is a ES6 thing)

So I got this component, lets call it and this component will receive an onClick function as a prop with one param, so we have <Component onClick={() => handleClick("clicked")}/>

This Component, has a callAll function and is implemented like this

const callAll = (...fns) => (...args) => fns.forEach(fn => fn && fn(...args))

const Component = ({children: child}) => {
return React.cloneElement(child, {
    onClick: callAll(() => setIsOpen(true), child.props.onClick),
  })
}

My question is where does the ...args come from, in the sense of how does the inner function of 'callAll' receive all the args of each specific function magically just by typing '...args'?

I hope I explained myself, thanks!

1 Answers

That const callAll... statement creates an arrow function that creates an arrow function when you call it. In traditional function syntax it would look like this:

function callAll(...fns) {
    return function(...args) {
        fns.forEach(function(fn) {
            fn && fn(...args);
        });
    };
}

So the argument(s) you pass callAll are the functions to call (which are gathered up into the fns array). When you call it, you get back a function that will call all of those functions with whatever arguments it's called with (which are gathered up into the args array):

const callLogAndError = callAll(console.log, console.error);
// fns −−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^
callLogAndError(1, 2, 3); 
// args −−−−−−−−^^^^^^^

Live example:

const callAll = (...fns) => (...args) => fns.forEach(fn => fn && fn(...args));

const callLogAndError = callAll(console.log, console.error);
// fns −−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^
callLogAndError(1, 2, 3); 
// args −−−−−−−−^^^^^^^

So later, in the onclick:

callAll(() => setIsOpen(true), child.props.onClick)

That creates a function that will call these two functions with the arguments it receives (which, with onClick, would be just the event object for the event):

  1. () => setIsOpen(true)
  2. child.props.onClick

That onClick could also have been written like this, without callAll:

onClick: (event) => {
    setIsOpen(true);
    child.props.onClick(event);
}
Related