编辑类型数组的可写对象时,Svelte UI 未正确更新
Svelte UI not properly updated when Writable of Type Array is edited
我目前正在为一家赛艇俱乐部开发船员创作者,以了解背景。
包含数组的Writable是这样声明的
import { writable, Writable } from 'svelte/store';
import type { CrewMember } from '../types';
export default writable<Writable<CrewMember>[]>([], () => {
console.log('Subscriber Detected ON CREW MEMBERS');
return () => console.log('No More Subscribers ON CREW MEMBERS');
});
这就是我从数组中删除特定项目的方式
members.update((currentList) => {
let tmp = currentList.filter((val) => {
if (val != mem) return true;
});
return tmp;
});
其中 mem
是传递给删除函数的 Writable<CrewMember>
。我也尝试过通过 ID 删除,但目前也没有用。
代码从列表中删除项目很好,但是它没有正确更新 UI,总是删除 table 的最后一项而不是删除的项目,这确实得到由于它们被推送到数据库而刷新页面时已修复。
会不会是因为我用的是 Writable<Writable<CrewMember>[]>
因为连我都知道这听起来很该死。
以下是导致问题的整个代码块
<script lang="ts">
import { onDestroy, onMount } from 'svelte';
import { get } from 'svelte/store';
import type { Writable } from 'svelte/store';
import type { CrewMember } from '../../types';
import CrewMemberListItem from './CrewMemberListItem.svelte';
export let members: Writable<Writable<CrewMember>[]>;
export let pushToBuffer: { (mem: Writable<CrewMember>): void };
let unsubscribe: { (): void };
function deleteMember(mem: Writable<CrewMember>) {
let member = get(mem);
if (!confirm(`Are you sure that you want to delete ${member.name}?`))
return;
member.delete().then(() => {
members.update((currentList) =>
currentList.filter((val) => val != mem)
);
});
}
onMount(() => {
unsubscribe = members.subscribe(
(_updatedValue: Writable<CrewMember>[]) => {
// internalMembersBuffer = updatedValue;
}
);
});
onDestroy(() => {
unsubscribe();
});
</script>
<table id="member-editor-list">
<tr class="header">
<th>Gender</th>
<th>Age Group</th>
<th class="left">Name</th>
<th>Actions</th>
</tr>
{#each $members as member}
<CrewMemberListItem
{member}
{pushToBuffer}
deleteFunction={deleteMember}
/>
{/each}
</table>
为了简单起见,删除了 css
感谢@pilchard 提醒我 keyed each
块的存在。这才是我应该一直使用的。
无需更改逻辑,但每个块现在应如下所示
{#each $members as member (get(member).id)}
<CrewMemberListItem
{member}
{pushToBuffer}
deleteFunction={deleteMember}
/>
{/each}
相对于此
{#each $members as member}
<CrewMemberListItem
{member}
{pushToBuffer}
deleteFunction={deleteMember}
/>
{/each}
看来 (get(member).id)
正在帮助 svelte 意识到这些差异很大,不能仅通过查看列表长度来正确更改 UI。
我的测试表明这可以按要求工作。给未来的自己 RTFM 的提示 :)
再次感谢@pilchard
我目前正在为一家赛艇俱乐部开发船员创作者,以了解背景。
包含数组的Writable是这样声明的
import { writable, Writable } from 'svelte/store';
import type { CrewMember } from '../types';
export default writable<Writable<CrewMember>[]>([], () => {
console.log('Subscriber Detected ON CREW MEMBERS');
return () => console.log('No More Subscribers ON CREW MEMBERS');
});
这就是我从数组中删除特定项目的方式
members.update((currentList) => {
let tmp = currentList.filter((val) => {
if (val != mem) return true;
});
return tmp;
});
其中 mem
是传递给删除函数的 Writable<CrewMember>
。我也尝试过通过 ID 删除,但目前也没有用。
代码从列表中删除项目很好,但是它没有正确更新 UI,总是删除 table 的最后一项而不是删除的项目,这确实得到由于它们被推送到数据库而刷新页面时已修复。
会不会是因为我用的是 Writable<Writable<CrewMember>[]>
因为连我都知道这听起来很该死。
以下是导致问题的整个代码块
<script lang="ts">
import { onDestroy, onMount } from 'svelte';
import { get } from 'svelte/store';
import type { Writable } from 'svelte/store';
import type { CrewMember } from '../../types';
import CrewMemberListItem from './CrewMemberListItem.svelte';
export let members: Writable<Writable<CrewMember>[]>;
export let pushToBuffer: { (mem: Writable<CrewMember>): void };
let unsubscribe: { (): void };
function deleteMember(mem: Writable<CrewMember>) {
let member = get(mem);
if (!confirm(`Are you sure that you want to delete ${member.name}?`))
return;
member.delete().then(() => {
members.update((currentList) =>
currentList.filter((val) => val != mem)
);
});
}
onMount(() => {
unsubscribe = members.subscribe(
(_updatedValue: Writable<CrewMember>[]) => {
// internalMembersBuffer = updatedValue;
}
);
});
onDestroy(() => {
unsubscribe();
});
</script>
<table id="member-editor-list">
<tr class="header">
<th>Gender</th>
<th>Age Group</th>
<th class="left">Name</th>
<th>Actions</th>
</tr>
{#each $members as member}
<CrewMemberListItem
{member}
{pushToBuffer}
deleteFunction={deleteMember}
/>
{/each}
</table>
为了简单起见,删除了 css
感谢@pilchard 提醒我 keyed each
块的存在。这才是我应该一直使用的。
无需更改逻辑,但每个块现在应如下所示
{#each $members as member (get(member).id)}
<CrewMemberListItem
{member}
{pushToBuffer}
deleteFunction={deleteMember}
/>
{/each}
相对于此
{#each $members as member}
<CrewMemberListItem
{member}
{pushToBuffer}
deleteFunction={deleteMember}
/>
{/each}
看来 (get(member).id)
正在帮助 svelte 意识到这些差异很大,不能仅通过查看列表长度来正确更改 UI。
我的测试表明这可以按要求工作。给未来的自己 RTFM 的提示 :)
再次感谢@pilchard