feat(atoms): dynamically update atom exports; improve export wrapping #256
+110
−7
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Since the inception of atom exports, they've always had the requirement of being "stable". When creating an exported function, you have to ensure the function doesn't close over any values that can become stale. This is because Zedux only sets the atom's exports after initial atom evaluation and never updates them.
Zedux does that because working with stable exports is much easier than trying to figure out when those exported function references change out from under you. Exports are not state, so there's no easy way to tell when the reference is updated. Basically, that would mean you should never destructure the exports off an atom:
Turning all exports into a JS Proxy wouldn't improve this DX either. But there is something we can do. Since atom apis already wrap functions by default, we can swap out the underlying function that Zedux's function wrapper wraps. This fixes the by-far most common scenario of an exported function closing over a stale value by allowing those exported function references to change while keeping the exposed function references stable for consumers.
Implement this dynamic wrapping. Also improve the wrapping logic's function detection to exclude classes themselves or any functions with static properties attached. All non-normal function values are still never updated after initial evaluation. And that's fine - any non-function values that are expected to update should be put in state (or the atom's promise).
TL;DR You can now do this: