Open adiguba opened 2 months ago
Maybe use $state.frozen
instead? REPL
As I understand it, there's no way to both make an object/array deeply reactive and maintain equality with the original object/array at the same time, since you have to add extra stuff to make it reactive, and you wouldn't want those extra stuff to propagate back to the original object.
I think this is more a documentation problem. Svelte uses proxies to make deep reactivity work, and thus equality of things you put in state will never match the same thing as what you put in, because they're all wrapped with proxies.
The workaround seems to reactify the searched value: the $state never creates wrappers (not sure how reliable this behaviour is). Basically:
const value = {};
$state(value) === $state(value); // true
$state(value) === $state($state(value)); // true
const arr = $state([ value ]);
arr.includes($state(value)); // true
The proxy could alter the behaviour of search methods, but it won't resolve cases like arrState[0] == rawObject
.
@dummdidumm I feel like the new warnings largely address this issue now.
There needs to be more docs on this, the warning itself is somewhat vague without any additional explanation IMO. It could come as part of the general "more details on a warning" system we can put in place with how warnings are setup now.
There needs to be more docs on this, the warning itself is somewhat vague without any additional explanation IMO. It could come as part of the general "more details on a warning" system we can put in place with how warnings are setup now.
It might be worth documenting now whilst it’s fresh in your head. I don’t personally think it’s all that needed so maybe your documentation can help me understand your thought process.
This should be addressed by https://github.com/sveltejs/svelte/pull/11613
This should be addressed by #11613
console.log( array[0] === obj ); // false !!!
console.log( array.indexOf(obj) ); // -1 !!!
console.log( array.findIndex(n => n === obj) ); // -1 !!!
Here is only for 1st line a solition in Svelte 5. For other two lines - here is nothing, but we can use a for loop.
I'm unhappy about so many extra runes... It looks like React now - solution for self created problems.
@dm-de It's not a problem if you reference things in state from the beginning. If you don't then you'll need to use $state.is
. This is just how JavaScript proxies work, if you'd rather not use them, and you'd rather use immutable objects instead then you have $state.frozen
where you don't need to worry about proxies.
items.findIndex(n => n === item); // WARN state_proxy_equality_mismatch
This is fine, and the warning message is explicit enough :
Reactive
$state(...)
proxies and the values they proxy have different identities. Because of this, comparisons with===
will produce unexpected results. Consider using$state.is(a, b)
instead
=> So a === b
should be replaced by $state.is(a, b)
:
- items.findIndex(n => n === item);
+ items.findIndex(n => $state.is(n, item));
👍
But for indexOf
the warning is ambiguous :
items.indexOf(item); // WARN state_proxy_equality_mismatch
Reactive
$state(...)
proxies and the values they proxy have different identities. Because of this, comparisons witharray.indexOf(...)
will produce unexpected results. Consider using$state.is(a, b)
instead
=> How do we replace array.indexOf(...)
with $state.is(a, b)
???
In fact here we should replace the indexOf()
by a findIndex()
:
- items.indexOf(item);
+ items.findIndex(n => $state.is(n, item));
So :
indexOf()
should be more explicit.indexOf()
/lastIndexOf()
.In "pseudo-code", the indexOf()
of an reactive array should be equivalent to :
indexOf(item) {
if (item!=null && typeof item === 'object) {
// item is an object, use findIndex()
return this.findIndex(n => $state.is(n, item));
} else {
return /* original indexOf() */
}
}
I still think Svelte should specifically handle calls to indexOf()/lastIndexOf()
We're getting into monkey-patching territory with this, and I'm pretty sure everyone agrees that we shouldn't do that.
Describe the bug
When we used an
$state([])
, some basic function of Array have an incorrect behavior with object. It seems that all equality operations fail, as the object in the array is a proxy.It’s really disturbing and not easy to understand...
Reproduction
Exemple in REPL : the buttons addRandomNumber, addRandomString and addRandomObject add a number/string/object in an array, and logs the index.
This works as espected for number and string, but fails for objects.
REPL
Logs
No response
System Info
Severity
annoyance