我有一个异步react-select组件
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();
// Gets called when an option is chosen or created.
const onChange = value => {
setFieldValue(value);
if (onSelect) onSelect(value);
};
// Toggle menu by presence of input.
// Reset value if input is emptied.
const onInputChange = (value, context) => {
if (!value && context.action === "input-change") {
onChange(null);
}
};
// Restore input value.
const onFocus = () => {
if (fieldValue) {
asyncRef.current.state.inputValue = fieldValue.label;
asyncRef.current.select.state.inputValue = fieldValue.label;
asyncRef.current.handleInputChange(fieldValue.label);
}
};
// Close menu when pressing enter. Submit does not work on mobile.
const onKeyDown = event => {
if (event.keyCode === 13) {
onMenuClose();
}
};
// Blur select element to trigger onFocus on next click.
const onMenuClose = () => {
asyncRef.current.select.blur();
};
return (
<>
<div ref={ref} />
<Async
ref={asyncRef}
{...props}
value={fieldValue}
components={components ? components : null}
loadOptions={loadOptions ? loadOptions : () => null}
placeholder={placeholder ? placeholder : "Select..."}
searchPromptText="Start Typing"
autoload
isSearchable
searchable
cacheOptions
// Hook into events to make the editing work.
onChange={onChange}
onInputChange={onInputChange}
onFocus={onFocus}
onKeyDown={onKeyDown}
onMenuClose={onMenuClose}
/>
</>
);
};
export default MySelect;我在另一个组件中使用此组件从输入值加载数组和筛选选项。
const loadOptions = async inputValue => {
return new Promise(resolve => resolve(getOptions(inputValue)));
};
const getOptions = async inputValue => {
// how to trigger this to be called within loadOptions when option is selected?
if (asyncOptions && asyncOptions.length > 0) {
const options = asyncOptions.filter(item =>
item.label.toLowerCase().startsWith(inputValue.trim().toLowerCase())
);
if (options && options.length > 0) {
return options;
}
return [];
}
await delayWithPromise(1000);
return [];
};
return (
<div className="App">
<MySelect
name="addressLookup"
className="addressLookupContainer"
label="Address Lookup"
asyncSelect
components={{
DropdownIndicator: () => null,
IndicatorSeparator: () => null,
NoOptionsMessage: val => <NoOptionsMsg>No Options</NoOptionsMsg>
}}
loadOptions={loadOptions}
onSelect={val => console.log(`${val.value} selected`)}
/>
</div>
);但是,我想要它,所以当我选择一个选项时,它会加载另一个列表(不关闭列表,而是在旧列表位置加载一个新列表),但是我不确定当我单击一个选项时,如何在loadOptions中重新触发react-select/async支持呢?
一个例子是地址搜索,其中搜索街道/post/邮政编码,并且有一个选项说明该街道有多少地址,然后选择该选项将触发loadOptions发出一个API调用以查找该街道上的所有地址,因此,引入一个新的选项列表。希望这有意义?
任何帮助都将不胜感激。
我有一个CodeSandbox和一个例子。
发布于 2020-07-09 15:42:24
我试了一下你发布的代码框链接。onSelect支柱可以用来检测用户是否选择了任何内容。
const [firstValue, setFirstValue] = useState("");
const [secondValue, setSecondValue] = useState("");
const onSelect = option => {
if (firstValue) setSecondValue(option?.value);
else setFirstValue(option?.value);
};现在我们知道,如果选择了firstValue,就需要切换这些选项。所以,按照这个逻辑-
const getOptions = async inputValue => {
const optionChunk = firstValue ? secondOptions : firstOptions;
if (optionChunk && optionChunk.length > 0) {
const options = optionChunk.filter(item =>
item.label.toLowerCase().startsWith(inputValue.trim().toLowerCase())
);
if (options && options.length > 0) {
return options;
}
return [];
}
await delayWithPromise(1000);
return [];
};有关更多细节,请查看代码框链接。我到处修改了几个可变的名字,这对我来说更有意义。
编辑
当用户选择第一个值时重新打开菜单-
所以,当我们有firstValue而不是secondValue时,我们可以传递一个prop(比方说- retainFocus) -
<MySelect
... otherProps
retainFocus={!!firstValue && !secondValue}
/>在MySelect中,我们可以在retainFocus上添加一个useEffect,如果以true的形式传递,这只会重新调整选中框的焦点。
useEffect(() => {
if (retainFocus) {
asyncRef.current.select.focus();
}
}, [retainFocus]);检查更新后的代码框链接。
编辑
我还添加了一个方法,以便在用户输入为空时返回到第一个列表。
https://stackoverflow.com/questions/62817284
复制相似问题