Skip to main content

‘运行时警告’

客户端警告(Client warnings)

¥Client warnings

assignment_value_stale

Assignment to `%property%` property (%location%) will evaluate to the right-hand side, not the value of `%property%` following the assignment. This may result in unexpected behaviour.

假设这种情况……

¥Given a case like this...

<script>
	let object = $state({ array: null });

	function add() {
		(object.array ??= []).push(object.array.length);
	}
</script>

<button onclick={add}>add</button>
<p>items: {JSON.stringify(object.items)}</p>

...首次单击按钮时推送到的数组是分配右侧的 [],但 object.array 的结果值是空状态代理。因此,推送的值将被丢弃。

¥...the array being pushed to when the button is first clicked is the [] on the right-hand side of the assignment, but the resulting value of object.array is an empty state proxy. As a result, the pushed value will be discarded.

你可以通过将其分成两个语句来解决这个问题:

¥You can fix this by separating it into two statements:

function function add(): voidadd() {
	
let object: {
    array: number[];
}
object
.array: number[]array ??= [];
let object: {
    array: number[];
}
object
.array: number[]array.Array<number>.push(...items: number[]): number

Appends new elements to the end of an array, and returns the new length of the array.

@paramitems New elements to add to the array.
push
(
let object: {
    array: number[];
}
object
.array: number[]array.Array<number>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
);
}

binding_property_non_reactive

`%binding%` is binding to a non-reactive property
`%binding%` (%location%) is binding to a non-reactive property

console_log_state

Your `console.%method%` contained `$state` proxies. Consider using `$inspect(...)` or `$state.snapshot(...)` instead

记录 proxy 时,浏览器 devtools 将记录代理本身而不是它所代表的值。在 Svelte 的情况下,$state 代理的 ‘target’ 可能与其当前值不相似,这可能会造成混淆。

¥When logging a proxy, browser devtools will log the proxy itself rather than the value it represents. In the case of Svelte, the ‘target’ of a $state proxy might not resemble its current value, which can be confusing.

记录随时间变化的值的最简单方法是使用 $inspect 符文。或者,要一次性记录内容(例如,在事件处理程序内部),你可以使用 $state.snapshot 获取当前值的快照。

¥The easiest way to log a value as it changes over time is to use the $inspect rune. Alternatively, to log things on a one-off basis (for example, inside an event handler) you can use $state.snapshot to take a snapshot of the current value.

event_handler_invalid

%handler% should be a function. Did you mean to %suggestion%?

hydration_attribute_changed

The `%attribute%` attribute on `%html%` changed its value between server and client renders. The client value, `%value%`, will be ignored in favour of the server value

<img> 元素上的某些属性(如 src)在水化期间不会被修复,即服务器值将被保留。这是因为更新这些属性可能会导致重新获取图片(或者在 <iframe> 的情况下,重新加载框架),即使它们解析为相同的资源。

¥Certain attributes like src on an <img> element will not be repaired during hydration, i.e. the server value will be kept. That’s because updating these attributes can cause the image to be refetched (or in the case of an <iframe>, for the frame to be reloaded), even if they resolve to the same resource.

要修复此问题,请用 svelte-ignore 注释使警告静音,或确保服务器和客户端之间的值保持不变。如果你确实需要在水合时更改值,你可以强制进行这样的更新:

¥To fix this, either silence the warning with a svelte-ignore comment, or ensure that the value stays the same between server and client. If you really need the value to change on hydration, you can force an update like this:

<script>
	let { src } = $props();

	if (typeof window !== 'undefined') {
		// stash the value...
		const initial = src;

		// unset it...
		src = undefined;

		$effect(() => {
			// ...and reset after we've mounted
			src = initial;
		});
	}
</script>

<img {src} />

hydration_html_changed

The value of an `{@html ...}` block changed between server and client renders. The client value will be ignored in favour of the server value
The value of an `{@html ...}` block %location% changed between server and client renders. The client value will be ignored in favour of the server value

如果 {@html ...} 值在服务器和客户端之间发生变化,则在水化期间不会修复它,即服务器值将被保留。这是因为水合期间的变化检测成本高昂且通常没有必要。

¥If the {@html ...} value changes between the server and the client, it will not be repaired during hydration, i.e. the server value will be kept. That’s because change detection during hydration is expensive and usually unnecessary.

要修复此问题,请用 svelte-ignore 注释使警告静音,或确保服务器和客户端之间的值保持不变。如果你确实需要在水合时更改值,你可以强制进行这样的更新:

¥To fix this, either silence the warning with a svelte-ignore comment, or ensure that the value stays the same between server and client. If you really need the value to change on hydration, you can force an update like this:

<script>
	let { markup } = $props();

	if (typeof window !== 'undefined') {
		// stash the value...
		const initial = markup;

		// unset it...
		markup = undefined;

		$effect(() => {
			// ...and reset after we've mounted
			markup = initial;
		});
	}
</script>

{@html markup}

hydration_mismatch

Hydration failed because the initial UI does not match what was rendered on the server
Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near %location%

当 Svelte 在从服务器提取 HTML 时遇到错误时,会抛出此警告。在 hydration 期间,Svelte 会遍历 DOM,期望具有一定的结构。如果该结构不同(例如,由于 HTML 无效,HTML 被 DOM 修复),则 Svelte 将遇到问题,导致此警告。

¥This warning is thrown when Svelte encounters an error while hydrating the HTML from the server. During hydration, Svelte walks the DOM, expecting a certain structure. If that structure is different (for example because the HTML was repaired by the DOM because of invalid HTML), then Svelte will run into issues, resulting in this warning.

在开发过程中,此错误前面通常会有一个 console.error,详细说明有问题的 HTML,需要修复。

¥During development, this error is often preceeded by a console.error detailing the offending HTML, which needs fixing.

invalid_raw_snippet_render

The `render` function passed to `createRawSnippet` should return HTML for a single element

legacy_recursive_reactive_block

Detected a migrated `$:` reactive block in `%filename%` that both accesses and updates the same reactive value. This may cause recursive updates when converted to an `$effect`.

lifecycle_double_unmount

Tried to unmount a component that was not mounted

ownership_invalid_binding

%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%

考虑三个组件 GrandParentParentChild。如果你执行 <GrandParent bind:value>,在 GrandParent 内部通过 <Parent {value} /> 传递变量(注意缺少 bind:),然后在 Parent 内部执行 <Child bind:value>,则会抛出此警告。

¥Consider three components GrandParent, Parent and Child. If you do <GrandParent bind:value>, inside GrandParent pass on the variable via <Parent {value} /> (note the missing bind:) and then do <Child bind:value> inside Parent, this warning is thrown.

要修复此问题,请将 bind: 设置为值,而不是仅传递属性(即在此示例中执行 <Parent bind:value />)。

¥To fix it, bind: to the value instead of just passing a property (i.e. in this example do <Parent bind:value />).

ownership_invalid_mutation

Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
%component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead

考虑以下代码:

¥Consider the following code:

App
<script>
	import Child from './Child.svelte';
	let person = $state({ name: 'Florida', surname: 'Man' });
</script>

<Child {person} />
<script lang="ts">
	import Child from './Child.svelte';
	let person = $state({ name: 'Florida', surname: 'Man' });
</script>

<Child {person} />
Child
<script>
	let { person } = $props();
</script>

<input bind:value={person.name}>
<input bind:value={person.surname}>
<script lang="ts">
	let { person } = $props();
</script>

<input bind:value={person.name}>
<input bind:value={person.surname}>

Child 正在改变 App 拥有的 person,而无需明确指定 “allowed” 来执行此操作。强烈不建议这样做,因为它会创建难以大规模推断的代码(”谁改变了这个值?”),因此发出警告。

¥Child is mutating person which is owned by App without being explicitly “allowed” to do so. This is strongly discouraged since it can create code that is hard to reason about at scale (“who mutated this value?”), hence the warning.

要修复此问题,请创建回调属性来传达更改,或将 person 标记为 $bindable

¥To fix it, either create callback props to communicate changes, or mark person as $bindable.

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

$state(...) 创建传递的值的 proxy。代理和值具有不同的身份,这意味着相等性检查将始终返回 false

¥$state(...) creates a proxy of the value it is passed. The proxy and the value have different identities, meaning equality checks will always return false:

<script>
	let value = { foo: 'bar' };
	let proxy = $state(value);

	value === proxy; // always false
</script>

要解决此问题,请确保你正在比较两个值都是用 $state(...) 创建的,或者两个值都不是。请注意,$state.raw(...) 不会创建状态代理。

¥To resolve this, ensure you’re comparing values where both values were created with $state(...), or neither were. Note that $state.raw(...) will not create a state proxy.

transition_slide_display

The `slide` transition does not work correctly for elements with `display: %value%`

slide 转换通过为元素的 height 制作动画来工作,这需要 display 样式,如 blockflexgrid。它不适用于:

¥The slide transition works by animating the height of the element, which requires a display style like block, flex or grid. It does not work for:

  • display: inline(这是 <span> 等元素的默认设置),以及其变体,如 inline-blockinline-flexinline-grid

    ¥display: inline (which is the default for elements like <span>), and its variants like inline-block, inline-flex and inline-grid

  • display: tabletable-[name]<table><tr> 等元素的默认值

    ¥display: table and table-[name], which are the defaults for elements like <table> and <tr>

  • display: contents

共享警告(Shared warnings)

¥Shared warnings

dynamic_void_element_content

`<svelte:element this="%tag%">` is a void element — it cannot have content

<input> 这样的元素不能有内容,传递给这些元素的任何子元素都将被忽略。

¥Elements such as <input> cannot have content, any children passed to these elements will be ignored.

state_snapshot_uncloneable

Value cannot be cloned with `$state.snapshot` — the original value was returned
The following properties cannot be cloned with `$state.snapshot` — the return value contains the originals:

%properties%

$state.snapshot 转换从可见状态开始,并逐渐擦除路径。某些对象可能无法克隆,在这种情况下将返回原始值。在下面的例子中,property 被克隆,但 window 没有被克隆,因为 DOM 元素是不可克隆的:

¥$state.snapshot tries to clone the given value in order to return a reference that no longer changes. Certain objects may not be cloneable, in which case the original value is returned. In the following example, property is cloned, but window is not, because DOM elements are uncloneable:

const 
const object: {
    property: string;
    window: Window & typeof globalThis;
}
object
=
function $state<{
    property: string;
    window: Window & typeof globalThis;
}>(initial: {
    property: string;
    window: Window & typeof globalThis;
}): {
    property: string;
    window: Window & typeof globalThis;
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);

https://svelte.dev/docs/svelte/$state

@paraminitial The initial value
$state
({ property: stringproperty: 'this is cloneable', window: Window & typeof globalThiswindow })
const
const snapshot: {
    property: string;
    window: {
        [x: number]: {
 [x: number]: ...;
 readonly clientInformation: {
   readonly clipboard: {
       read: {};
       readText: {};
       write: {};
       writeText: {};
       addEventListener: {};
       dispatchEvent: {};
       removeEventListener: {};
   };
   ... 41 more ...;
   readonly storage: {
       ...;
   };
 };
 ... 207 more ...;
 readonly sessionStorage: {
   ...;
 };
        };
        ... 921 more ...;
        undefined: undefined;
    };
}
snapshot
=
namespace $state
function $state<T>(initial: T): T (+1 overload)

Declares reactive state.

Example:

let count = $state(0);

https://svelte.dev/docs/svelte/$state

@paraminitial The initial value
$state
.
function $state.snapshot<{
    property: string;
    window: Window & typeof globalThis;
}>(state: {
    property: string;
    window: Window & typeof globalThis;
}): {
    property: string;
    window: {
        ...;
    };
}

To take a static snapshot of a deeply reactive $state proxy, use $state.snapshot:

Example:

&#x3C;script>
  let counter = $state({ count: 0 });

  function onclick() {
	// Will log `{ count: ... }` rather than `Proxy { ... }`
	console.log($state.snapshot(counter));
  };
&#x3C;/script>

https://svelte.dev/docs/svelte/$state#$state.snapshot

@paramstate The value to snapshot
snapshot
(
const object: {
    property: string;
    window: Window & typeof globalThis;
}
object
);
上一页 下一页