Conversation

It seems like useCallback roughly doubles the code size whenever I do it. Here's an actual screenshot of what it takes to satisfy the linter with and without useCallback. This is the actual example that prompted these tweets.
Image
6
1
12
In this approach, the HTMLButtonElement (or whatever) gets assigned a callback that doesn't change over time, but that callback closes over an object (the ref) whose field (current) changes to the latest function literal whenever the hook's parent is dirtied.
1
Interesting. I haven't tried this in code, but I can imagine situations where this would genuinely violate the dependencies that should be in place. E.g. if you conditionally define a callback to be one function body or another, then pass it down. Right?
2
(I can't think of a reason that that would be necessary, but I'm just trying to imagine what the possible failure modes are here. If that's the worst one then maybe it's fine?)
1
Sorry, I misunderstood. I think I'm still not really understanding. What happens if the function passed to useByrefCallback closes over some locals like props etc.? Won't it capture them as they were at definition time and hold those references forever?
2
No: if the props change, the component calling useByrefCallback will rerender, which will create a new closure capturing the new props, which will then be stored in the hook’s inner ref.current.
1
(the closure *returned* from useByrefCallback will be the same, but calling useByrefCallback with the new closure literal will have the side effect that the unchanged returned closure now calls the new closure literal)
1
I think using refs as general mutable boxes isn’t idiomatic to many JS developers—they only grok them for referring to React element nodes. Late-binding event callbacks and mutable boxes are pretty common tactics in Cocoa-land, so I guess I was primed.
2