首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在react中触发loadOptions --单击“选择/异步”选项

在react中触发loadOptions --单击“选择/异步”选项
EN

Stack Overflow用户
提问于 2020-07-09 14:33:26
回答 1查看 4.5K关注 0票数 0

我有一个异步react-select组件

代码语言:javascript
复制
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;

我在另一个组件中使用此组件从输入值加载数组和筛选选项。

代码语言:javascript
复制
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和一个例子。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-09 15:42:24

我试了一下你发布的代码框链接。onSelect支柱可以用来检测用户是否选择了任何内容。

代码语言:javascript
复制
  const [firstValue, setFirstValue] = useState("");
  const [secondValue, setSecondValue] = useState("");

  const onSelect = option => {
    if (firstValue) setSecondValue(option?.value);
    else setFirstValue(option?.value);
  };

现在我们知道,如果选择了firstValue,就需要切换这些选项。所以,按照这个逻辑-

代码语言:javascript
复制
    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) -

代码语言:javascript
复制
<MySelect
   ... otherProps
   retainFocus={!!firstValue && !secondValue}
/>

MySelect中,我们可以在retainFocus上添加一个useEffect,如果以true的形式传递,这只会重新调整选中框的焦点。

代码语言:javascript
复制
  useEffect(() => {
    if (retainFocus) {
      asyncRef.current.select.focus();
    }
  }, [retainFocus]);

检查更新后的代码框链接

编辑

我还添加了一个方法,以便在用户输入为空时返回到第一个列表。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62817284

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档