如何在react-select/async中选中选项后重新触发loadOptions
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
- Add state to control the menu visibility and input value
- Pass the selected value to your
loadOptionsfunction - Force the menu to stay open after selection
- 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
menuIsOpenstate overrides react-select's default behavior to keep the dropdown open after selection. - Contextual Loading: The wrapped
loadOptionsfunction 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
loadOptionsfunction triggers a fresh data fetch with the new selection context.
内容的提问来源于stack exchange,提问作者mcclosa
相关产品推荐
相关产品推荐

