You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte中选择AutoComplete值后InputChip组件不更新的问题

解决Skeleton UI InputChip在AutoComplete选择后不更新的问题

问题分析

你遇到的核心问题是:AutoComplete选择分类后,selectedCategoryChips数组已更新,但InputChip组件的UI未同步。这是因为状态冗余导致的响应式冲突——你通过$: selectedCategoryChips = selectedCategoryLabels同步状态,但InputChip的bind:value会直接修改selectedCategoryChips的引用,打乱了原有同步逻辑,最终导致UI未触发更新。

解决方案

简化状态管理,直接维护InputChip绑定的数组变量,同时确保selectedCategoryIds与芯片标签数组的一致性:

<script lang="ts">
  import { page } from "$app/stores";
  import { createQuery } from "@tanstack/svelte-query";
  import LoadingSpinner from "$lib/components/ui/LoadingSpinner.svelte";
  import {
    toastStore,
    InputChip,
    Autocomplete,
    type AutocompleteOption
  } from "@skeletonlabs/skeleton";

  const { supabase } = $page.data;

  export let selectedCategoryIds: string[] = [];
  export let subcatPaths: string[] = [];

  let whitelist: string[] = [];
  let selectedCategoryChips: string[] = [];
  let categoryOptions: AutocompleteOption[] = [];
  let inputChipCategory: string;

  $: categories = createQuery({
    queryKey: ["categories"],
    queryFn: async () => {
      const { data: cats, error } = await supabase.from("categories").select();
      if (error) throw error;

      return cats.map(
        (category) =>
          ({
            label: category.label,
            value: category.id,
            keywords: category.keywords
          } as AutocompleteOption)
      );
    },
    onSuccess: (data) => {
      categoryOptions = data;
      whitelist = data.map((category) => category.label);
      // 初始化:根据已选ID匹配对应标签
      selectedCategoryChips = data
        .filter(cat => selectedCategoryIds.includes(cat.value as string))
        .map(cat => cat.label);
    },
    onError: (err) => {
      console.log(err);
      toastStore.trigger({
        message: "Error fetching categories.",
        background: "variant-filled-error"
      });
    }
  });

  function onCategorySelect(event: CustomEvent<AutocompleteOption>) {
    const selectedValue = event.detail.value as string;
    const selectedLabel = event.detail.label as string;
    
    if (!selectedCategoryIds.includes(selectedValue)) {
      // 更新ID数组(保持响应式:重新创建数组)
      selectedCategoryIds = [...selectedCategoryIds, selectedValue];
      // 直接更新芯片标签数组,触发InputChip更新
      selectedCategoryChips = [...selectedCategoryChips, selectedLabel];
      // 清空输入框,提升体验
      inputChipCategory = '';
    }
  }

  // 监听芯片变化,同步更新ID数组(处理用户手动删除芯片的场景)
  $: if (categoryOptions.length > 0) {
    selectedCategoryIds = selectedCategoryChips
      .map(label => categoryOptions.find(opt => opt.label === label)?.value as string)
      .filter(id => id);
  }
</script>

<div class="label">
  <span>Categories</span>
  <InputChip
    {whitelist}
    allowUpperCase
    bind:input={inputChipCategory}
    bind:value={selectedCategoryChips}
    name="chips"
    placeholder="Enter 3 categories..."
    chips="variant-filled-primary"
    min="3"
  />
</div>

<div
  class="card w-full max-h-48 {$categories.isLoading
    ? 'p-4'
    : 'p-1'} overflow-y-auto"
>
  {#if $categories.isLoading}
    <center>
      <LoadingSpinner />
    </center>
  {:else if $categories.isSuccess}
    <Autocomplete
      options={categoryOptions}
      denylist={selectedCategoryIds}
      bind:input={inputChipCategory}
      on:selection={onCategorySelect}
    />
  {/if}
</div>

修改要点

  1. 移除冗余状态:删除selectedCategoryLabels变量,直接操作selectedCategoryChips(即InputChip绑定的数组),避免状态同步冲突。
  2. 直接触发响应式:在选择分类时,通过展开运算符重新创建数组,确保Svelte检测到状态变化并更新UI。
  3. 双向同步状态:添加响应式监听,当用户手动删除芯片时,自动同步更新selectedCategoryIds,保证两个数组的一致性。
  4. 初始化匹配:在分类数据加载完成后,根据初始的selectedCategoryIds自动生成对应的芯片标签。

内容的提问来源于stack exchange,提问作者Alexander Hunter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:16:22