0

I came across this code in the documentation for an NPM lib I was considering.

Coud someone attempt to explain to me what at least the first line is doing? It appears that the 3 => bits imply that these functions all return functions.

I consider myself (perhaps wrongly) passably good at javascript. The way thisis put together seems overly convoluted, at least clear obvious to me. I suppose if I could a bit more if tried hard enough, but something about this just feels overly confusing, so I moved on to another library.

The first line, and order of assignment, where functions start and stop is the least for me.

const withTimer = timerProps => WrappedComponent => wrappedComponentProps => (
  <Timer {...timerProps}>
    {timerRenderProps =>
      <WrappedComponent {...wrappedComponentProps} timer={timerRenderProps} />}
  </Timer>
);

class TimerWrapper extends React.Component {
    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <div>
                <div>Simple text</div>
                <Timer.Consumer>
                    {() => this.props.timer.getTime()}
                </Timer.Consumer>
            </div>
        );
    }
}

const TimerHOC = withTimer({
    initialTime: 5000,
})(TimerWrapper);

<TimerHOC />
pixelearth
  • 13,674
  • 10
  • 62
  • 110

1 Answers1

2

It is essentially this

function withTimer(timerProps) {
    function withWrappedComponent(WrappedComponent) {
        function withWrappedComponentProps(wrappedComponentProps) {
            return (
                <Timer {...timerProps}>
                    {(timerRenderProps) => (
                        <WrappedComponent {...wrappedComponentProps} timer={timerRenderProps} />
                    )}
                </Timer>
            );
        }
        return withWrappedComponentProps;
    }
    return withWrappedComponent;
}

If that helps

Alternatively as a sort of intermediary between both forms, it is like this

function withTimer(timerProps) {
    return function (WrappedComponent) {
        return function (wrappedComponentProps) {
            return (
                <Timer {...timerProps}>
                    {(timerRenderProps) => (
                        <WrappedComponent {...wrappedComponentProps} timer={timerRenderProps} />
                    )}
                </Timer>
            );
        };
    };
}
Countingstuff
  • 733
  • 5
  • 14
  • It seemed you had to add some named functions here that weren't in the orig. Is there an equivalent with anon funcs? – pixelearth Dec 07 '20 at 21:03
  • yep, I have written it with anon funcs now – Countingstuff Dec 07 '20 at 21:04
  • That does help. But it's still hard to read for me, and I wonder why this type of nesting is necessary. I write react frequently and haven't ever had to resort to something like this. Maybe it's just a limitation on my level of sophistication. It seems at least like the first to layers of nesting could be combined into one, and nothing would be lost. Am I wrong? `const TimerHOC = withTimerAndWrapper({...}, TimerWrapper)` – pixelearth Dec 07 '20 at 21:11
  • Hmm well, now you're asking more for reasoning behind why to do it. I wouldn't say it's a limitation of your sophistication, but it is a legitimate pattern in functional style programming. The idea is that these 'curried' functions, where you can pass in arguments one at a time, provide nice composition, and then you can pass in just functions to places and avoid passing in lots of arguments solely for the purpose of calling the function at the bottom level. Personally I think this example does look a /little/ silly. – Countingstuff Dec 07 '20 at 21:16
  • You're not wrong the first two layers of nesting could be combined and I personally would probably do so. That being said, suppose that you have a root level config file C which defines these timer props. And you have multiple implementations of a Timer, say Timer1 and Timer2. Then it /might/ be nice to be able to do at a high level, `const TimerConfig = withTimer (C)` and pass in TimerConfig to various places, and later on do TimerConfig(Timer1) and TimerConfig(Timer2). And now you've avoided having to pass C down or read it in a strange place, while still maintaing dependency injection. – Countingstuff Dec 07 '20 at 21:23