React-Select Async loadOptions未正确加载选项 [英] React-Select Async loadOptions is not loading options properly

查看:212
本文介绍了React-Select Async loadOptions未正确加载选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

反应异步选择加载选项有时无法加载该选项.在几个查询集合反应后,这是一个非常奇怪的现象.loadoptions未加载任何值,但我从日志中可以看到,结果正确地来自后端查询.我的代码库与react-select新版本并使用

React Async Select loadoption sometimes fail to loads the option. This is a very strange phenomenon after couple of set of queries react loadoptions don't load any value but i can see from log that results properly came from backend query. My codebase is totally up to date with react-select new release and using

反应选择":"^ 2.1.1"

"react-select": "^2.1.1"

这是我的react-async select组件的前端代码.我确实在我的getOptions函数中使用了反跳,以减少后端搜索查询的数量.我猜这应该不会造成任何问题.我想补充一点,在这种情况下,我观​​察到的是,loadoptions serach指示器(...)也没有出现在这种现象中.

Here is my front end code for react-async select component. I do use debounce in my getOptions function to reduce number of backend search query. This should not cause any problem i guess. I would like to add another point that i observe in this case, loadoptions serach indicator ( ... ) also not appear in this phenomenon.

import React from 'react';
import AsyncSelect from 'react-select/lib/Async';
import Typography from '@material-ui/core/Typography';
import i18n from 'react-intl-universal';

const _ = require('lodash');

class SearchableSelect extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: '',
      searchApiUrl: props.searchApiUrl,
      limit: props.limit,
      selectedOption: this.props.defaultValue
    };
    this.getOptions = _.debounce(this.getOptions.bind(this), 500);
    //this.getOptions = this.getOptions.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.noOptionsMessage = this.noOptionsMessage.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleChange(selectedOption) {
    this.setState({
      selectedOption: selectedOption
    });
    if (this.props.actionOnSelectedOption) {
      // this is for update action on selectedOption
      this.props.actionOnSelectedOption(selectedOption.value);
    }
  }

  handleInputChange(inputValue) {
    this.setState({ inputValue });
    return inputValue;
  }

  async getOptions(inputValue, callback) {
    console.log('in getOptions'); // never print
    if (!inputValue) {
      return callback([]);
    }
    const response = await fetch(
      `${this.state.searchApiUrl}?search=${inputValue}&limit=${
        this.state.limit
      }`
    );
    const json = await response.json();
    console.log('results', json.results); // never print
    return callback(json.results);
  }

  noOptionsMessage(props) {
    if (this.state.inputValue === '') {
      return (
        <Typography {...props.innerProps} align="center" variant="title">
          {i18n.get('app.commons.label.search')}
        </Typography>
      );
    }
    return (
      <Typography {...props.innerProps} align="center" variant="title">
        {i18n.get('app.commons.errors.emptySearchResult')}
      </Typography>
    );
  }
  getOptionValue = option => {
    return option.value || option.id;
  };

  getOptionLabel = option => {
    return option.label || option.name;
  };

  render() {
    const { defaultOptions, placeholder } = this.props;
    return (
      <AsyncSelect
        cacheOptions
        value={this.state.selectedOption}
        noOptionsMessage={this.noOptionsMessage}
        getOptionValue={this.getOptionValue}
        getOptionLabel={this.getOptionLabel}
        defaultOptions={defaultOptions}
        loadOptions={this.getOptions}
        placeholder={placeholder}
        onChange={this.handleChange}
      />
    );
  }
}

export default SearchableSelect;

编辑以回答史蒂夫的答案

谢谢您的回答,史蒂夫.仍然没有运气.我会尝试根据您的回应点来回应.

Edit to response Steve's answer

Thank you for your answer Steve. Still no luck. I try to response according to your response points.

  1. 如果我不使用optionsValue,而是使用getOptionValue和getOptionLevel,那么查询结果将无法正确加载.我的意思是加载了空白选项,没有文本值.
  2. 是的,是的,这是一个返回字符串的同步方法,我不需要重写它.并且此工作正常,并且noOptionsMessage正确显示.感谢指出这一点.
  3. actionOnSelectedOption不是noop方法,它可能有一定责任要执行.我尝试将SearchableSelect用作独立组件,如果我需要一些后端操作来执行此功能,则会相应地触发该操作.例如,我在项目的用户配置文件中使用它,用户可以在其中从现有条目中更新他的学校/学院信息.当用户选择一个选项时,将执行配置文件更新责任.
  4. 是的,您是正确的.我不需要保持inputValue的状态,谢谢.
  5. 我确实确保defaultOptions是一个数组.
  6. 我不使用防抖功能进行测试,但仍然没有运气.我正在使用去抖动来限制后端调用,否则对于我肯定不希望的每个按键都可能有一个后端调用.

异步选择非常适合2/3查询,此后突然停止工作.我观察到一种可区分的行为,对于这些情况,搜索指示符(...)也未显示.

async select work perfectly for 2/3 queries and after that it suddenly stop working. One distinguishable behaviour i observe that for those cases search indicators ( ... ) also not showing.

非常感谢您抽出宝贵的时间.

Thank you so much for you time.

非常感谢您的回复.我对getOptionValue和getOptionLabel错误.如果loadOptions得到响应,则将调用这两个函数.所以我从以前的代码片段中删除了我的helper optionsValue函数,并根据(也在本帖子中)更新了我的代码片段.但是仍然没有运气.在某些情况下,异步选择无效.我尝试对这种情况进行截图.我在本地数据库名称"tamim johnson"中使用了名称,但是当我搜索他时,我没有得到任何回应,但从后端获得了适当的回应.这是此案例的屏幕截图

Thank you so much for your response again. I was wrong about getOptionValue and getOptionLabel. If loadOptions got response both these function called. So i removed my helper optionsValue function from my previous code snippet and update my code-snippet according to ( In this post also ). But still no luck. In some cases async-select didn't work. I try to take a screenshot one such case. I do name use in my local-db name "tamim johnson" but when i search him i didn't get any response but got proper response back from back-end. Here is the screenshot of this case

我不确定此屏幕截图的清晰度如何.塔米姆·约翰逊(Tamim Johnson)在我的排名中也排名第六.

I not sure how clear this screenshot is. Tamim johnson also in 6th position in my ranklist.

谢谢您的时间.我不知道我在做什么错或错过了什么.

Thank you sir for your time. I have no clue what i am doing wrong or missing something.

这是名为"tamim johnson"的用户搜索的预览选项卡响应.

This is preview tab response for user search named "tamim johnson".

推荐答案

我发现人们打算寻找这个问题.因此,我要发布解决问题的代码的更新部分.从异步等待转换为正常的回调函数解决了我的问题.特别感谢史蒂夫和其他人.

I found out that people intend to look for this problem. So i am posting my update portion of code that fix the issue. Converting from async-await to normal callback function fix my issue. Special thanks to Steve and others.

import React from 'react';
import AsyncSelect from 'react-select/lib/Async';
import { loadingMessage, noOptionsMessage } from './utils';
import _ from 'lodash';

class SearchableSelect extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedOption: this.props.defaultValue
    };
    this.getOptions = _.debounce(this.getOptions.bind(this), 500);
  }

  handleChange = selectedOption => {
    this.setState({
      selectedOption: selectedOption
    });
    if (this.props.actionOnSelectedOption) {
      this.props.actionOnSelectedOption(selectedOption.value);
    }
  };

  mapOptionsToValues = options => {
    return options.map(option => ({
      value: option.id,
      label: option.name
    }));
  };

  getOptions = (inputValue, callback) => {
    if (!inputValue) {
      return callback([]);
    }

    const { searchApiUrl } = this.props;
    const limit =
      this.props.limit || process.env['REACT_APP_DROPDOWN_ITEMS_LIMIT'] || 5;
    const queryAdder = searchApiUrl.indexOf('?') === -1 ? '?' : '&';
    const fetchURL = `${searchApiUrl}${queryAdder}search=${inputValue}&limit=${limit}`;

    fetch(fetchURL).then(response => {
      response.json().then(data => {
        const results = data.results;
        if (this.props.mapOptionsToValues)
          callback(this.props.mapOptionsToValues(results));
        else callback(this.mapOptionsToValues(results));
      });
    });
  };

  render() {
    const { defaultOptions, placeholder, inputId } = this.props;
    return (
      <AsyncSelect
        inputId={inputId}
        cacheOptions
        value={this.state.selectedOption}
        defaultOptions={defaultOptions}
        loadOptions={this.getOptions}
        placeholder={placeholder}
        onChange={this.handleChange}
        noOptionsMessage={noOptionsMessage}
        loadingMessage={loadingMessage}
      />
    );
  }
}

export default SearchableSelect;

这篇关于React-Select Async loadOptions未正确加载选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆