|
| 1 | +--- |
| 2 | +pageClass: "rule-details" |
| 3 | +sidebarDepth: 0 |
| 4 | +title: "svelte/infinite-reactive-loop" |
| 5 | +description: "Svelte runtime prevents calling the same reactive statement twice in a microtask. But between different microtask, it doesn't prevent." |
| 6 | +--- |
| 7 | + |
| 8 | +# svelte/infinite-reactive-loop |
| 9 | + |
| 10 | +> Svelte runtime prevents calling the same reactive statement twice in a microtask. But between different microtask, it doesn't prevent. |
| 11 | +
|
| 12 | +- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge> |
| 13 | + |
| 14 | +## :book: Rule Details |
| 15 | + |
| 16 | +Svelte runtime prevents calling the same reactive statement twice in a microtask.<br/> |
| 17 | +But between different microtask, it doesn't prevent.<br/> |
| 18 | +This rule reports those possible infinite loop. |
| 19 | + |
| 20 | +<ESLintCodeBlock> |
| 21 | + |
| 22 | +<!--eslint-skip--> |
| 23 | + |
| 24 | +```svelte |
| 25 | +<script> |
| 26 | + /* eslint svelte/infinite-reactive-loop: "error" */ |
| 27 | + import { count } from "./store.js" |
| 28 | + import { tick } from "svelte" |
| 29 | + let a = 0 |
| 30 | +
|
| 31 | + // ✓ GOOD |
| 32 | + $: if (a < 10) { |
| 33 | + a += 1 |
| 34 | + $count += 1 |
| 35 | + } |
| 36 | +
|
| 37 | + $: (async () => { |
| 38 | + // You can update a state in the same micro task. |
| 39 | + a += 1 |
| 40 | + $count += 1 |
| 41 | + await new Promise((resolve) => setTimeout(resolve, 100)) |
| 42 | + })() |
| 43 | +
|
| 44 | + $: (async () => { |
| 45 | + await doSomething_ok() |
| 46 | + })() |
| 47 | +
|
| 48 | + const doSomething_ok = async () => { |
| 49 | + await fetchFromServer() |
| 50 | + // You can update a state even in different microtask |
| 51 | + // if you don't refer the state in reactive statement. |
| 52 | + a += 1 |
| 53 | + } |
| 54 | +
|
| 55 | + // ✗ BAD |
| 56 | + $: (async () => { |
| 57 | + await doSomething() |
| 58 | + // Do not update a state in different micro task. |
| 59 | + a += 1 |
| 60 | + $count += 1 |
| 61 | + })() |
| 62 | +
|
| 63 | + $: tick(() => { |
| 64 | + a = a + 1 |
| 65 | + $count += 1 |
| 66 | + }) |
| 67 | +
|
| 68 | + $: (async () => { |
| 69 | + console.log(a) |
| 70 | + // This rule checks caller function recursively. |
| 71 | + await doSomething_ng_1() |
| 72 | + })() |
| 73 | +
|
| 74 | + const doSomething_ng_1 = async () => { |
| 75 | + a += 1 |
| 76 | + await fetchFromServer() |
| 77 | + doSomething_ng_2() |
| 78 | + } |
| 79 | +
|
| 80 | + const doSomething_ng_2 = () => { |
| 81 | + a += 1 |
| 82 | + } |
| 83 | +</script> |
| 84 | +``` |
| 85 | + |
| 86 | +</ESLintCodeBlock> |
| 87 | + |
| 88 | +## :wrench: Options |
| 89 | + |
| 90 | +Nothing. |
| 91 | + |
| 92 | +## :books: Further Reading |
| 93 | + |
| 94 | +- [Svelte - Docs > COMPONENT FORMAT > 3. $: marks a statement as reactive](https://svelte.dev/docs#component-format-script-3-$-marks-a-statement-as-reactive) |
| 95 | +- [Svelte - Docs > COMPONENT FORMAT > 4. Prefix stores with $ to access their values](https://svelte.dev/docs#component-format-script-4-prefix-stores-with-$-to-access-their-values) |
| 96 | + |
| 97 | +## :mag: Implementation |
| 98 | + |
| 99 | +- [Rule source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/src/rules/infinite-reactive-loop.ts) |
| 100 | +- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/infinite-reactive-loop.ts) |
0 commit comments