-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
fix: allow $store to be used with changing values including nullish values #7947
Conversation
Thanks @Conduitry for identifying as a duplicate. I searched in GitHub but must have entered a wrong keyword combination or simply missed it (there are many results for words like "store", "undefined", etc.). 🙂 |
test/runtime/samples/store-auto-subscribe-removed-store/_config.js
Outdated
Show resolved
Hide resolved
test/runtime/samples/store-auto-subscribe-removed-store/_config.js
Outdated
Show resolved
Hide resolved
@tanhauhau Do you know why the tests suddenly failed? It seems like a random failure of an unrelated test, only on macOS. I don't have permissions to re-run. |
it's okay. recently the tests are a bit flaky. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost LGTM but I added 1 comment.
src/runtime/internal/utils.ts
Outdated
@@ -66,6 +66,9 @@ export function validate_store(store, name) { | |||
|
|||
export function subscribe(store, ...callbacks) { | |||
if (store == null) { | |||
for (const callback of callbacks) { | |||
callback(store); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1st argument of callback
is a value of store, so in this case, the value is undefined right?
value of null/undefined is undefined.
callback(store); | |
callback(undefined); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But null !== undefined
. This is returning the same value passed, and preserving runtime correctness as checked by TypeScript.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding store.value
,
if store
is null, store.value
= null.value
. value
is undefined.
if store
is undefined, store.value
= undefined.value
. value
is undefined.
First argument of callback
is value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see an implicit conversion of null
into undefined
in the linked section, but my reading skills this morning aside - it seems to match the runtime behavior that exists today (minus this bug) 🙂 REPL confirming null -> undefined
If this is the desired behavior, the types for TypeScript need to be fixed too. This code right now fails to compile:
let nameStore = null;
let name: undefined;
$: name = $nameStore;
Type 'null' is not assignable to type 'undefined'.
That's why I wrote the PR the way I did.
I'm observing a difference in behavior with this change. This code: <script>
import { writable, derived } from "svelte/store";
let name = null;
$: d = derived(name, (e) => {
console.log(e);
});
setTimeout(() => (name = writable("hi")), 1000);
setTimeout(() => (name = null), 2000);
</script>
{$name}
{$d} will print the following in the current version:
With this PR it prints only
The reason this happens is that Question is, if passing a falsy value to
I slightly lean towards b or c. Either way, we should have a test that codifies this behavior. |
IMO is c. |
That's a very good point, we can't do b) . I think I vote for a) then. The types already says "should be defined". |
@dummdidumm Part of your sample code above, though, was That's not to say I'm convinced that b) is definitely a better option than a). I remember feeling very conflicted about this when you brought it up last month. But I don't think we should rule out b) as technically infeasible, as far as I can tell. |
Mhm true... we need to find out what happens if you derive from multiple stores and one of them gets undefined. |
Added some tests, which was good to see that const a = writable(1);
const b = derived([a, null, undefined], ([n, un1, un2]) => {
// I will never end up in here, due to the inner `pending` variable of `derived` never being false
return n * 2;
}); The fix is to either fill up any falsy stores with Which now begs the question, if this derived(undefined, () => {
// call this or not call this?
});
--> option b) to me feels inconsistent now. From a typings perspective having a falsy value is invalid already (TS will yell at you). From a backwards-compatible and code-golf perspective (you need less code for the fallback than for the error message) I still lean towards c) Thoughts? |
@dummdidumm is attempting to deploy a commit to the Svelte Team on Vercel. A member of the Team first needs to authorize it. |
We decided to error for falsy derived inputs |
This aims to fix #7946 and fix #7555 by having
utils.js/subscribe
call the callbacks even if the store is nullish.Related PR: #7693
Before submitting the PR, please make sure you do the following
[feat]
,[fix]
,[chore]
, or[docs]
.Tests
npm test
and lint the project withnpm run lint