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

React Select下拉菜单因国旗加载卡顿,useTransition使用问题求助

解决React Select加载大量国旗卡顿问题

原代码问题分析

你把setMenuIsOpen(true)放在了startTransition回调里,这会把菜单打开的操作标记为低优先级过渡任务,导致React先完成其他渲染工作后才会显示菜单,和你想要的"立即打开菜单"需求完全相反。

修正方案:分离菜单打开与国旗加载逻辑

核心思路是:菜单打开操作立即执行,将国旗的渲染逻辑放入过渡任务中延迟执行,避免阻塞UI。

修正后的代码

import axios from "axios";
import React from "react";
import { useTransition, useEffect, useState } from "react";
import Select from "react-select";
import Flag from "react-world-flags";

const ReactSelectFlag = () => {
  const [countries, setCountries] = useState([]);
  const [isPending, startTransition] = useTransition();
  const [menuIsOpen, setMenuIsOpen] = useState(false);
  const [showFlags, setShowFlags] = useState(false);

  useEffect(() => {
    axios.get("v1/countries").then(res => {
      setCountries(res.data.data);
    });
  }, []);

  const handleMenuOpen = () => {
    // 立即打开菜单,不放入过渡任务
    setMenuIsOpen(true);
    // 在过渡中触发国旗渲染,降低该操作优先级
    startTransition(() => {
      setShowFlags(true);
    });
  };

  const handleMenuClose = () => {
    setMenuIsOpen(false);
    setShowFlags(false);
  };

  return (
    <Select
      options={countries}
      getOptionValue={option => option?.id}
      menuIsOpen={menuIsOpen}
      onMenuOpen={handleMenuOpen}
      onMenuClose={handleMenuClose}
      getOptionLabel={option => (
        <div style={{ display: "flex", alignItems: "center" }}>
          {/* 仅当showFlags为true时渲染国旗 */}
          {showFlags && (
            <span style={{ marginRight: "6px" }}>
              <Flag code={option?.code} width="24px" height="14px" />
            </span>
          )}
          {option?.code} - {option?.name}
        </div>
      )}
      // 可选:添加过渡期间的加载提示
      components={{
        Option: props => {
          if (isPending && !showFlags) {
            return <div style={{ padding: "0.5rem" }}>加载国旗中...</div>;
          }
          return <Select.Option {...props} />;
        }
      }}
    />
  );
};

export default ReactSelectFlag;

关键改动说明

  1. 新增showFlags状态,控制国旗的渲染时机
  2. handleMenuOpen中先直接调用setMenuIsOpen(true),确保菜单立即显示
  3. 将setShowFlags(true)放入startTransition,让React在空闲时渲染国旗,避免阻塞菜单打开的UI操作
  4. 可选:通过自定义Option组件,在过渡期间显示加载提示,提升用户体验

进阶优化:虚拟滚动

如果国旗加载仍然存在性能问题,推荐使用虚拟滚动插件,只渲染可视区域内的选项,大幅减少DOM节点数量:

// 先安装依赖
// npm install react-select-virtualized
import VirtualizedSelect from 'react-select-virtualized';

const ReactSelectFlag = () => {
  // ... 其他状态和逻辑不变

  return (
    <VirtualizedSelect
      options={countries}
      getOptionValue={option => option?.id}
      menuIsOpen={menuIsOpen}
      onMenuOpen={handleMenuOpen}
      onMenuClose={handleMenuClose}
      getOptionLabel={option => (
        <div style={{ display: "flex", alignItems: "center" }}>
          <span style={{ marginRight: "6px" }}>
            <Flag code={option?.code} width="24px" height="14px" />
          </span>
          {option?.code} - {option?.name}
        </div>
      )}
      // 设置菜单高度,限制可视区域
      menuHeight={400}
    />
  );
};

内容的提问来源于stack exchange,提问作者Rahil Əliyev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:55:40