3 ms·
> Closures work exactly the same as they always do, but they're also something a lot of people struggle with and always have. Its not normal for a render funct
by spion 4y ago
> Closures work exactly the same as they always do, but they're also something a lot of people struggle with and always have.
Its not normal for a render function to run all the time but the closures mentioned in it to be completely ignored. Thats completely the opposite of how most other APIs work in the language. Usually, a (constructor) function runs once, and the closures returned by it may get run multiple times. Completely ignoring the passed closures to hooks in many/most cases is something very specific to React.
- rimunroe 4y ago> Its not normal for a render function to run all the time but the closures mentioned in it to be completely ignored. Thats completely the opposite of how most other APIs work in the language. Usually, a (constructor) function runs once, and the closures returned by it may get run multiple times. React function components are not constructor functions though, so I don't see how those are relevant. Bringing up the expectation that constructors "only run once" in the context of how hooks are hard to reason about seems strange though, as class component constructor functions have to be written in a way where they can potentially run multiple times. I think that's been a requirement for the entire time React has supported JavaScript classes. What do you mean by "closures returned by a constructor function"? Do you mean the instance and its associated methods? If so, yes, running a constructor obviously produces one instance[1], which is true in React too. But you're never invoking that constructor yourself--and you never should have been doing that with React in the first place--so why would that matter? Also, I'm confused, can you point at a comparable API to a React function component in the JavaScript language? [1] well, sort of. Constructors can return any arbitrary object, so the following works class Foo { constructor(n) { return new Number(n); } } let foo = new Foo(1); foo instanceof Foo; // false foo instanceof Number; // true
- spion 4y ago> React function components are not constructor functions though, so I don't see how those are relevant I'm giving an example of whats a normal use case of closures. Running a single function once that creates closures that run zero, one, or multiple times is "normal". Running a single function multiple times that creates closures that run one time and get ignored all other calls of the function is not.
- rimunroe 4y ago> Running a single function multiple times that creates closures that run one time and get ignored all other calls of the function is not. This exactly describes a leading-edge debounce function, which I was asked in multiple interviews early in my career to implement on a whiteboard. I'll admit that "problems people feel like giving to junior devs" isn't a great method of measuring whether or not something is simple, but I think it is indicative of how widely that sort of thing is expected to be understood. It also exactly describes any sort of request framework where request responses are cached after the first call and the result is returned without a network hit in subsequent calls.
- spion 4y agoI would typically save the result of calling debounce (once), then call that, rather than calling debounce over and over on the same inline function (hooks style). My debounce implementation would *not* be trying to catter to some API that looks like this: render() { debounce(() => { justCallCodeHere(); moreLines(); }) debounce(() => { anotherFunction(); moreLines(); }) } but more something like this constructor() { // called only once this.debouncedFn1 = debounce(() => { justCallCodeHere(); moreLines(); }) this.debouncedFn2 = debounce(() => { anotherFunction(); moreLines(); }) } render() { // use the created debounced functions this.debouncedFn1() this.debouncedFn2() } How would you implement the first version without having access to react hooks? Keep in mind that in every call to debounce, the function object you get as an argument is unique because unique closures get created on every call of render(). I hope that illustrates the key weirdness aspect of hooks.
- rimunroe 4y agoYes, that's true in this case, but it's not unusual to have something which uniquely identifies a debounced/memoized/cached function though, so that subsequent calls look it up against a registry and avoid repeated computation. In the context of requests, that's usually the URL itself (or some combination of the URL and some parameters). This sort of registry is basically exactly what a component instance serves as is in the context of hooks.