楚河之界 2022-07-15 10:37 采纳率: 97.4%
浏览 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 在虚拟机中配置flume,无法将slave1节点的文件采集到master节点中
  • ¥15 husky+kinova jaco2 仿真
  • ¥15 MATLAB数据处理
  • ¥15 zigbee终端设备入网失败
  • ¥15 金融监管系统怎么对7+4机构进行监管的
  • ¥15 硬件IIC从模式的数据发送,中断数据的接收,不能用HAL库(按照时序图)
  • ¥20 QAxWidget上显示一个word文档后,如何直接在该QAxWidget上修改和保存word文档
  • ¥15 Simulink仿真报错,请问如何解决
  • ¥20 宝塔面板无法添加Node项目,一直处于正在添加脚本页面
  • ¥50 Dkeil5 CT107D单片机的程序编写