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

如何在react-select/async中选中选项后重新触发loadOptions

Solution: Keep Menu Open and Re-trigger loadOptions on Selection

To achieve your goal of keeping the dropdown open and reloading options when an item is selected (like in an address lookup flow), we need to modify your MySelect component to control the menu state and pass selection context to your loadOptions function. Here's how to implement it step by step:

Key Modifications to MySelect

  1. Add state to control the menu visibility and input value
  2. Pass the selected value to your loadOptions function
  3. Force the menu to stay open after selection
  4. Manually trigger a reload of options when an item is selected

Updated MySelect Component

import React, { useRef, useState } from "react";
import Async from "react-select/async";

const MySelect = ({ label, options, asyncSelect, loadOptions, components, placeholder, fixedHeight, onSelect, ...props }) => {
  const ref = useRef();
  const asyncRef = useRef();
  const [fieldValue, setFieldValue] = useState();
  const [inputValue, setInputValue] = useState("");
  const [menuIsOpen, setMenuIsOpen] = useState(false);

  // Handle option selection: keep menu open and trigger option reload
  const onChange = (value) => {
    setFieldValue(value);
    onSelect?.(value);
    
    // Keep menu open after selection
    setMenuIsOpen(true);
    // Reset input to trigger fresh option load (adjust this based on your needs)
    setInputValue("");
    // Manually trigger loadOptions with the new selection context
    asyncRef.current?.loadOptions(inputValue);
  };

  // Manage input value state and reset selection if input is cleared
  const onInputChange = (value, context) => {
    setInputValue(value);
    if (!value && context.action === "input-change") {
      onChange(null);
    }
  };

  // Open menu and restore input value when focusing the component
  const onFocus = () => {
    setMenuIsOpen(true);
    if (fieldValue) {
      const restoredInput = fieldValue.label;
      setInputValue(restoredInput);
      asyncRef.current?.handleInputChange(restoredInput);
    }
  };

  // Close menu on Enter key press (mobile-friendly)
  const onKeyDown = (event) => {
    if (event.keyCode === 13) {
      setMenuIsOpen(false);
    }
  };

  // Blur component only when menu is intentionally closed
  const onMenuClose = () => {
    if (!menuIsOpen) {
      asyncRef.current?.select.blur();
    }
  };

  // Wrap loadOptions to pass the currently selected value to the parent
  const wrappedLoadOptions = async (inputVal) => {
    return loadOptions?.(inputVal, fieldValue) ?? [];
  };

  return (
    <>
      <div ref={ref} />
      <Async
        ref={asyncRef}
        {...props}
        value={fieldValue}
        inputValue={inputValue}
        components={components ?? null}
        loadOptions={wrappedLoadOptions}
        placeholder={placeholder ?? "Select..."}
        searchPromptText="Start Typing"
        autoload
        isSearchable
        cacheOptions
        menuIsOpen={menuIsOpen} // Force menu to stay open based on our state
        onChange={onChange}
        onInputChange={onInputChange}
        onFocus={onFocus}
        onKeyDown={onKeyDown}
        onMenuClose={onMenuClose}
      />
    </>
  );
};

export default MySelect;

Updated Parent Component Usage

Modify your loadOptions function to use the selected value parameter to load context-specific options (e.g., addresses for a selected street):

// Simulate API call to load addresses for a selected street
const fetchAddresses = async (streetId) => {
  await delayWithPromise(1000);
  return [
    { label: `${streetId} - 123 Main St`, value: `${streetId}-123` },
    { label: `${streetId} - 456 Main St`, value: `${streetId}-456` },
    { label: `${streetId} - 789 Main St`, value: `${streetId}-789` },
  ];
};

const loadOptions = async (inputValue, selectedValue) => {
  // If a value is selected, load options based on that selection
  if (selectedValue) {
    return fetchAddresses(selectedValue.value);
  }

  // Original search logic: filter streets/zip codes by input
  if (asyncOptions && asyncOptions.length > 0) {
    const options = asyncOptions.filter(item => 
      item.label.toLowerCase().startsWith(inputValue.trim().toLowerCase())
    );
    return options.length > 0 ? options : [];
  }
  await delayWithPromise(1000);
  return [];
};

return (
  <div className="App">
    <MySelect
      name="addressLookup"
      className="addressLookupContainer"
      label="Address Lookup"
      asyncSelect
      components={{
        DropdownIndicator: () => null,
        IndicatorSeparator: () => null,
        NoOptionsMessage: () => <NoOptionsMsg>No Options</NoOptionsMsg>
      }}
      loadOptions={loadOptions}
      onSelect={val => console.log(`${val.value} selected`)}
    />
  </div>
);

How It Works

  • Menu Visibility: The menuIsOpen state overrides react-select's default behavior to keep the dropdown open after selection.
  • Contextual Loading: The wrapped loadOptions function passes the currently selected value to your parent component's logic, allowing you to load options specific to the selected item.
  • Input Control: Resetting the input value after selection ensures the loadOptions function triggers a fresh data fetch with the new selection context.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:12:43