【问题标题】:Svelte UI not properly updated when Writable of Type Array is edited编辑可写类型数组时,Svelte UI 未正确更新
【发布时间】:2021-08-30 21:36:06
【问题描述】:

我目前正在为划船俱乐部制作船员创建器以获取上下文。

包含数组的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&lt;CrewMember&gt;。我也尝试过按 ID 删除,但也没有成功。

代码从列表中删除项目就好了,但是它没有正确更新 UI,总是删除表的最后一项而不是删除的项目,这在刷新页面时会得到修复,因为它们是推送到数据库。

会不会是因为我使用的是 Writable&lt;Writable&lt;CrewMember&gt;[]&gt;,因为即使我也知道这听起来该死的诅咒。

以下是导致问题的整个代码块

<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 被移除

【问题讨论】:

  • mem 似乎未定义
  • 第二个代码块可以替换为members.update((currentList) =&gt; currentList.filter((val) =&gt; val != mem))
  • 您使用的是keyed each 吗?听起来像是渲染问题而不是商店问题
  • @pilchard 是正确的,问题在于渲染,因为通过 API 中的请求和显示删除功能删除正确元素之前和之后的注销列表显示逻辑工作正常.但是 UI 建议它每次只删除最后一个元素,我假设这是对 svelte 的优化,但我不知道如何解决它。
  • 请提供一个最小的可重现示例,例如使用REPL

标签: javascript arrays typescript svelte


【解决方案1】:

感谢@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2022-01-23
    • 2020-12-04
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多