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

如何将react-select Async组件的已选项排到列表顶部

React-Select Async组件实现已选项置顶的解决方案

问题背景

需要让下拉选项中的已选项排到列表顶部,普通Select组件通过onChange事件已实现该功能,但Async组件因loadOptions采用回调加载选项的机制,相同逻辑无法生效。初始选项排序为Option 1、Option 2、Option 3、Option 4,目前Async组件选中选项后无法置顶。

问题根源

Async组件每次触发搜索(输入内容)时,都会调用loadOptions并通过回调返回新的选项列表,这会直接覆盖你通过onChange维护的asyncOptions状态,导致之前的排序逻辑被重置。

解决方案

核心思路是单独维护已选中的选项状态,在loadOptions返回结果时,主动将已选中的选项合并到结果列表的顶部,同时确保已选项不会重复出现在列表中。

修改后的完整代码

import React, { useRef, useState } from "react";

import AsyncSelect from "react-select/async";
import Select from "react-select";
import { options as baseOptions } from "./options";

const filterColors = (inputValue: string) => {
  return baseOptions.filter((i) =>
    i.label.toLowerCase().includes(inputValue.toLowerCase())
  );
};

export default () => {
  /** Select 组件原有有效逻辑 */
  const initialOptions = useRef(baseOptions);
  const [options, setOptions] = useState(initialOptions.current);

  function onSelectChange(newOptions, action) {
    const stateOptions =
      initialOptions.current?.filter((option) => {
        return !newOptions.find((newOpt) => newOpt.value === option.value);
      }) ?? [];
    const updatedOptions = newOptions?.concat(stateOptions);
    setOptions(updatedOptions);
  }

  /** Async 组件改造逻辑 */
  // 单独维护已选中的选项集合
  const [selectedAsyncOptions, setSelectedAsyncOptions] = useState([]);

  // 改造loadOptions,返回结果时合并已选中选项到顶部
  const loadAsyncOptions = (inputValue: string, callback: (options) => void) => {
    setTimeout(() => {
      const filteredOptions = filterColors(inputValue);
      // 过滤掉已选中的选项,避免列表重复显示
      const unselectedOptions = filteredOptions.filter(
        opt => !selectedAsyncOptions.find(selected => selected.value === opt.value)
      );
      // 重组列表:已选中选项 + 未选中选项
      const finalOptions = [...selectedAsyncOptions, ...unselectedOptions];
      callback(finalOptions);
    }, 1000);
  };

  function onAsyncChange(newOptions, action) {
    // 仅更新已选中选项的状态
    setSelectedAsyncOptions(newOptions);
  }

  return (
    <>
      <label>Select</label>
      <Select
        isClearable
        isMulti
        hideSelectedOptions={false}
        onChange={onSelectChange}
        options={options}
      />

      <label>Async</label>
      <AsyncSelect
        loadOptions={loadAsyncOptions}
        defaultOptions
        isMulti
        hideSelectedOptions={false}
        onChange={onAsyncChange}
      />
    </>
  );
};

关键修改说明

  1. 拆分状态管理:新增selectedAsyncOptions状态专门存储已选中的选项,不再维护完整的options列表
  2. 拦截选项返回逻辑:在loadAsyncOptions的回调阶段,先过滤掉已选中的选项,再将已选中选项拼接到结果列表的最前端
  3. 简化onChange逻辑:onAsyncChange只负责更新已选中选项的状态,不再手动重组整个选项列表
  4. 移除冗余属性:AsyncSelect组件不再手动传入options,完全由loadOptions返回处理后的列表

效果验证

修改后,选中Async组件的选项后,无论是否进行搜索操作,下拉列表中的已选项都会固定显示在顶部,和普通Select组件的效果完全一致。

内容的提问来源于stack exchange,提问作者Shea Leslein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 19:47:49