docs: tweak `$state.is` warning (#12599)

Also add a detailed explanation which can later appear on the docs site

closes #11556
pull/12605/head
Simon H 5 months ago committed by GitHub
parent afa3128d2f
commit 3515776009
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -40,4 +40,24 @@
## state_proxy_equality_mismatch
> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead
> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead%details%
`$state(...)` does create a proxy of the value it is passed. Therefore, the resulting object has a different identity and equality checks will always return `false`:
```svelte
<script>
let object = { foo: 'bar' };
let state_object = $state(object);
object === state_object; // always false
</script>
```
Most of the time this will not be a problem in practise because it is very rare to keep the original value around to later compare it against a state value. In case it happens, Svelte will warn you about it in development mode and suggest to use `$state.is` instead, which is able to unwrap the proxy and compare the original values:
```svelte
<script>
let object = { foo: 'bar' };
let state_object = $state(object);
$state.is(object, state_object); // true
</script>
```

@ -33,7 +33,7 @@ for (const category of fs.readdirSync('messages')) {
const sections = text.trim().split('\n\n');
let details = null;
if (!sections[sections.length - 1].startsWith('> ')) {
while (!sections[sections.length - 1].startsWith('> ')) {
details = /** @type {string} */ (sections.pop());
}

@ -20,7 +20,10 @@ export function init_array_prototype_warnings() {
const test = indexOf.call(get_proxied_value(this), get_proxied_value(item), from_index);
if (test !== -1) {
w.state_proxy_equality_mismatch('array.indexOf(...)');
w.state_proxy_equality_mismatch(
'array.indexOf(...)',
': `array.findIndex(entry => $state.is(entry, item))`'
);
}
}
@ -42,7 +45,10 @@ export function init_array_prototype_warnings() {
);
if (test !== -1) {
w.state_proxy_equality_mismatch('array.lastIndexOf(...)');
w.state_proxy_equality_mismatch(
'array.lastIndexOf(...)',
': `array.findLastIndex(entry => $state.is(entry, item))`'
);
}
}
@ -56,7 +62,10 @@ export function init_array_prototype_warnings() {
const test = includes.call(get_proxied_value(this), get_proxied_value(item), from_index);
if (test) {
w.state_proxy_equality_mismatch('array.includes(...)');
w.state_proxy_equality_mismatch(
'array.includes(...)',
': `array.some(entry => $state.is(entry, item))`'
);
}
}
@ -79,7 +88,7 @@ export function init_array_prototype_warnings() {
*/
export function strict_equals(a, b, equal = true) {
if ((a === b) !== (get_proxied_value(a) === get_proxied_value(b))) {
w.state_proxy_equality_mismatch(equal ? '===' : '!==');
w.state_proxy_equality_mismatch(equal ? '===' : '!==', '');
}
return (a === b) === equal;
@ -93,7 +102,7 @@ export function strict_equals(a, b, equal = true) {
*/
export function equals(a, b, equal = true) {
if ((a == b) !== (get_proxied_value(a) == get_proxied_value(b))) {
w.state_proxy_equality_mismatch(equal ? '==' : '!=');
w.state_proxy_equality_mismatch(equal ? '==' : '!=', '');
}
return (a == b) === equal;

@ -114,12 +114,13 @@ export function ownership_invalid_mutation(component, owner) {
}
/**
* Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead
* Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead%details%
* @param {string} operator
* @param {string} details
*/
export function state_proxy_equality_mismatch(operator) {
export function state_proxy_equality_mismatch(operator, details) {
if (DEV) {
console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead`, bold, normal);
console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead${details}`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("state_proxy_equality_mismatch");

Loading…
Cancel
Save