Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useMutableSource: Allow returning function from getSnapshot #18921

Closed
wants to merge 1 commit into from

Conversation

sophiebits
Copy link
Collaborator

basicStateReducer strikes again.

@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit b4cf5b0:

Sandbox Source
youthful-chaum-wokl5 Configuration

@dai-shi
Copy link
Contributor

dai-shi commented May 14, 2020

@sophiebits Does this seem to fix #18823?

@sizebot
Copy link

sizebot commented May 14, 2020

No significant bundle size changes to report.

Size changes (experimental)

Generated by 🚫 dangerJS against b4cf5b0

@sizebot
Copy link

sizebot commented May 14, 2020

No significant bundle size changes to report.

Size changes (stable)

Generated by 🚫 dangerJS against b4cf5b0

@sophiebits
Copy link
Collaborator Author

@dai-shi It should.

@@ -1012,7 +1012,8 @@ function useMutableSource<Source, Snapshot>(
const latestSetSnapshot = refs.setSnapshot;

try {
latestSetSnapshot(latestGetSnapshot(source._source));
const value = latestGetSnapshot(source._source);
latestSetSnapshot(() => value);

// Record a pending mutable source update with the same expiration time.
const suspenseConfig = requestCurrentSuspenseConfig();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nb: we still need to support some kind of unwrapping because of the exceptions a few lines below this – we could maybe make something different for that to avoid allocating the function in the success case, but… I feel like this is fine?)

@acdlite
Copy link
Collaborator

acdlite commented May 15, 2020

Do we actually want to support this or is it more about defining a behavior that's currently poorly defined?

Using a function as your "snapshot" only works if it's pure/idempotent. It doesn't work if it reads from anything mutable (including the source itself).

I can't think of any legit use cases for this. Maybe to make an expensive computation lazy, but that's a subtle thing to get right because you have to pluck out the inputs before closing over them. I would consider that a very advanced use case, and there are other ways to get around it, like by wrapping the computation in an object: { readMemoizedComputation() }

As an alternative, could we say we don't support functions as snapshots and warn in dev if we detect one?

@sophiebits
Copy link
Collaborator Author

@dai-shi's use case of storing a constant function in your store like a state setter (https://github.com/dai-shi/use-context-selector/tree/v2) doesn't seem unreasonable to me, though it's not how I would write the code.

But more I noticed this while reading the code and I don't like things that are ostensibly agnostic to the value you put in them except fail on certain ones for no good reason – I assumed it was an oversight.

@@ -1012,7 +1012,8 @@ function useMutableSource<Source, Snapshot>(
const latestSetSnapshot = refs.setSnapshot;

try {
latestSetSnapshot(latestGetSnapshot(source._source));
const value = latestGetSnapshot(source._source);
latestSetSnapshot(() => value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an issue that I chatted about with Daishi a few weeks back, which has this obvious fix but... I had hoped to avoid the [almost always] unnecessary function wrapper. Still don't know how I feel about it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andrew's comment just loaded in for me after writing mine.

I agree with the concern he mentions about opening up extra problem cases if the function itself closes over mutable values.

As an alternative, could we say we don't support functions as snapshots and warn in dev if we detect one?

I tend to like this better.

@acdlite
Copy link
Collaborator

acdlite commented May 15, 2020

Another option is to use useReducer instead. However, we have plans to fork the useState and useReducer implementations so we can optimize useState for simple cases that can quickly bail out. So that might not work longer term.

OTOH, we've talked about making it so useState won't support multiple priority levels; that is, if you update at multiple priorities, both of them will get batched together, because that allows us to eagerly compute the final value without worrying that the reducer might change (since it's always basicStateReducer). That trade off works best when the updates are local. Doesn't work as well when the updates are entangled with lots of other updates across the whole app, as would often be the case with Flux store-like sources that useMutableSource is designed for.

Regardless I still kinda prefer not supporting this and warning.

@bvaughn
Copy link
Contributor

bvaughn commented May 15, 2020

I've posted a potential alternative for discussion #18933

@stale
Copy link

stale bot commented Aug 16, 2020

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Aug 16, 2020
@bvaughn
Copy link
Contributor

bvaughn commented Aug 16, 2020

We decided not to support this, but to warn instead (#18933). Just forgot to close the issue.

@bvaughn bvaughn closed this Aug 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Resolution: Stale Automatically closed due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants