fix: update `state_referenced_locally` message (#15733)

* fix: update state_referenced_locally message

* changeset

* update message
pull/15738/head
Rich Harris 5 months ago committed by GitHub
parent 02448a9acd
commit 95a020acea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: update `state_referenced_locally` message

@ -823,15 +823,16 @@ See [the migration guide](v5-migration-guide#Snippets-instead-of-slots) for more
### state_referenced_locally
```
State referenced in its own scope will never update. Did you mean to reference it inside a closure?
This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
```
This warning is thrown when the compiler detects the following:
- A reactive variable is declared
- the variable is reassigned
- the variable is referenced inside the same scope it is declared and it is a non-reactive context
- ...and later reassigned...
- ...and referenced in the same scope
In this case, the state reassignment will not be noticed by whatever you passed it to. For example, if you pass the state to a function, that function will not notice the updates:
This 'breaks the link' to the original state declaration. For example, if you pass the state to a function, the function loses access to the state once it is reassigned:
```svelte
<!--- file: Parent.svelte --->

@ -54,14 +54,15 @@ To fix this, wrap your variable declaration with `$state`.
## state_referenced_locally
> State referenced in its own scope will never update. Did you mean to reference it inside a closure?
> This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
This warning is thrown when the compiler detects the following:
- A reactive variable is declared
- the variable is reassigned
- the variable is referenced inside the same scope it is declared and it is a non-reactive context
- ...and later reassigned...
- ...and referenced in the same scope
In this case, the state reassignment will not be noticed by whatever you passed it to. For example, if you pass the state to a function, that function will not notice the updates:
This 'breaks the link' to the original state declaration. For example, if you pass the state to a function, the function loses access to the state once it is reassigned:
```svelte
<!--- file: Parent.svelte --->

@ -7,6 +7,7 @@ import * as e from '../../../errors.js';
import * as w from '../../../warnings.js';
import { is_rune } from '../../../../utils.js';
import { mark_subtree_dynamic } from './shared/fragment.js';
import { get_rune } from '../../scope.js';
/**
* @param {Identifier} node
@ -111,7 +112,34 @@ export function Identifier(node, context) {
(parent.type !== 'AssignmentExpression' || parent.left !== node) &&
parent.type !== 'UpdateExpression'
) {
w.state_referenced_locally(node);
let type = 'closure';
let i = context.path.length;
while (i--) {
const parent = context.path[i];
if (
parent.type === 'ArrowFunctionExpression' ||
parent.type === 'FunctionDeclaration' ||
parent.type === 'FunctionExpression'
) {
break;
}
if (
parent.type === 'CallExpression' &&
parent.arguments.includes(/** @type {any} */ (context.path[i + 1]))
) {
const rune = get_rune(parent, context.state.scope);
if (rune === '$state' || rune === '$state.raw') {
type = 'derived';
break;
}
}
}
w.state_referenced_locally(node, node.name, type);
}
if (

@ -641,11 +641,13 @@ export function reactive_declaration_module_script_dependency(node) {
}
/**
* State referenced in its own scope will never update. Did you mean to reference it inside a closure?
* This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
* @param {null | NodeLike} node
* @param {string} name
* @param {string} type
*/
export function state_referenced_locally(node) {
w(node, 'state_referenced_locally', `State referenced in its own scope will never update. Did you mean to reference it inside a closure?\nhttps://svelte.dev/e/state_referenced_locally`);
export function state_referenced_locally(node, name, type) {
w(node, 'state_referenced_locally', `This reference only captures the initial value of \`${name}\`. Did you mean to reference it inside a ${type} instead?\nhttps://svelte.dev/e/state_referenced_locally`);
}
/**

@ -2,6 +2,7 @@
let obj = $state({ a: 0 });
let count = $state(0);
let doubled = $derived(count * 2);
let tripled = $state(count * 3);
console.log(obj);
console.log(count);

@ -1,26 +1,38 @@
[
{
"code": "state_referenced_locally",
"message": "State referenced in its own scope will never update. Did you mean to reference it inside a closure?",
"message": "This reference only captures the initial value of `count`. Did you mean to reference it inside a derived instead?",
"start": {
"column": 22,
"line": 5
},
"end": {
"column": 27,
"line": 5
}
},
{
"code": "state_referenced_locally",
"message": "This reference only captures the initial value of `count`. Did you mean to reference it inside a closure instead?",
"start": {
"column": 13,
"line": 7
"line": 8
},
"end": {
"column": 18,
"line": 7
"line": 8
}
},
{
"code": "state_referenced_locally",
"message": "State referenced in its own scope will never update. Did you mean to reference it inside a closure?",
"message": "This reference only captures the initial value of `doubled`. Did you mean to reference it inside a closure instead?",
"start": {
"column": 13,
"line": 8
"line": 9
},
"end": {
"column": 20,
"line": 8
"line": 9
}
}
]

Loading…
Cancel
Save