楚河之界 2022-07-15 10:37 采纳率: 100%
浏览 70
已结题

使用React-Autosuggest遇到的问题

React中使用的Autosuggest这个第三方插件
问题描述:首次在input输入任意内容后,随后全部删除,当清空后会报如下错误。然后再次输入,再次清空,则不会报错。
从描述来看,是因为非受控组件变成受控才导致的问题。请问有什么解决办法吗?

img

下面是示例代码,没贴样式

const AsyncAutoComplete = ({ inputField, hooks, onChange, section, ...props }) => {
  const { loadAsyncDropdown} = useForm(hooks);
  const [optionValue, setValue] = useState('');
  const [options, setOptions] = useState([]);
  const [cache, setcache] = useState({});
  const [timer, setTimer] = useState(0);
 // 设置缓存
  const setCache = (key, options) => {
    // 无法找到匹配则设置一个空项
    if (options.length === 0) options = [{ label: 'No Options', value: '' }];
    cache[key] = options;
    // 同时缓存返回数据中的数据项
    options.forEach((i) => {
      cache[i.value] = [i];
    });
    return options;
  };
  // 获取关键字数据,有缓存从缓存获取否则从远程服务器加载
  const getData = async (value, bySearch = false) => {
    let options;
    if (value === '') {
      cache.empty = [{ label: 'No Options', value: '' }];
      options = cache.empty;
    } else if (cache[value]) {
      options = cache[value];
    } else {
      options = await loadAsyncDropdown(inputField, value);
      options = options.options;
      options = setCache(value, options);
    }
    setOptions(options);
    if (options.length === 1 && options[0].value) onChange(options[0]);
    else if (bySearch) {
      document.querySelector('#myinput').focus();
    }
    return options;
  };

  const search = async () => {
    clearTimeout(timer); // 清空计时器,防止没法查询
    if (optionValue.length > 2) {
      getData(optionValue, true);
    }
  };

  // 点击下拉弹出层时返回需要的内容,labe和value一样随便一个
  const getSuggestionValue = (suggestion) => suggestion.value;
  // 渲染弹出层的每个项的格式
  const renderSuggestion = (suggestion) => <div>{suggestion.label}</div>;
  // 输入框输入内容时响应的事件
  const onInput = async (newValue) => {
    setValue(newValue);
    if (newValue.length === 0) {
      // 清空内容
      onChange({ label: '', value: '' });
    } else if (newValue.length === 13) getData(newValue);
  };
  const onBlur = (e) => {
    let t = setTimeout(() => {
      let item = cache[optionValue];
      if (!item || item.length !== 1 || item[0].value !== optionValue) {
        setValue(''); // 清空内容
        onChange({}); // 更新其他组件值
      }
    }, 200); 
    setTimer(t);
  };
  const onClick = () => {
    let el = document.querySelector('#myinput');
    el.selectionStart = 0;
    el.selectionEnd = 0;
  };
  const onKeyDown = (e) => {
    let el = document.querySelector('#myinput');
    if (el.selectionStart === 0 && optionValue.length > 0) {
      setValue('');
    }
  };
  const inputProps = {
    placeholder: "输入关键字查找",
    value: optionValue || '',
    onChange: (e, obj) => {
      onInput(obj.newValue);
    },
    id: 'myinput',
    onBlur,
    onClick,
    onKeyDown,
  };
  const onSuggestionsClearRequested = () => {
    setOptions([]);
  };
  const onSuggestionsFetchRequested = async ({ value }) => {
    if (value.length === 13) {
      getData(value);
    }
  };
  return (
    <>
        <div>
          <Autosuggest
            suggestions={options}
            onSuggestionsClearRequested={onSuggestionsClearRequested}
            onSuggestionsFetchRequested={() => {}}
            getSuggestionValue={getSuggestionValue}
            renderSuggestion={renderSuggestion}
            inputProps={inputProps}
          />
          <SearchIcon onClick={search}  />
        </div>
      )}
    </>
};

export default AsyncAutoComplete;

AsyncAutoComplete.propTypes = {
  inputField: PropTypes.shape({
    name: PropTypes.string.isRequired,
    placeholder: PropTypes.string.isRequired,
    isRequired: PropTypes.bool.isRequired,
    isEnabled: PropTypes.bool.isRequired,
    isTouched: PropTypes.bool.isRequired,
    isValid: PropTypes.bool.isRequired,
    errorMsg: PropTypes.string.isRequired,
  }).isRequired,
  onChange: PropTypes.func.isRequired,
};
  • 写回答

2条回答 默认 最新

  • CSDN专家-showbo 2022-07-15 14:28
    关注

    onInput只更新内容,不做其他操作会出错了?只能一步一步来排除到底哪个出问题了。
    const onInput = async (newValue) => {
    setValue(newValue);
    return
    if (newValue.length === 0) {
    // 清空内容
    onChange({ label: '', value: '' });
    } else if (newValue.length === 13) getData(newValue);
    };

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 8月30日
  • 已采纳回答 8月22日
  • 创建了问题 7月15日

悬赏问题

  • ¥15 我想在一个软件里添加一个优惠弹窗,应该怎么写代码
  • ¥15 fluent的在模拟压强时使用希望得到一些建议
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用
  • ¥15 Web.config连不上数据库
  • ¥15 我想付费需要AKM公司DSP开发资料及相关开发。
  • ¥15 怎么配置广告联盟瀑布流