从输入字段的api动态获取建议

时间:2018-04-17 20:57:01

标签: javascript reactjs

我正在尝试获取反应组件中输入字段的建议。我在这个输入字段上触发onChange事件,然后进行api调用并获取相关内容。

这就是我这样做的方式

<span>
    <input type="text" placeholder="Add tag" list="languages" id='tags-input-field'
           className={`addtag-input ${this.state.showAddTagInputArray.findIndex(x => x === item.id) !== -1 ? "" : "hidden"}`}
           onChange={this.searchTags.bind(this)}
           />
    <datalist id='languages'>
        {this.state.existingTags && this.state.existingTags.map((item,i)=>{
            return <option value= {item.name} />
        })}
    </datalist>
</span>

这是&#34; searchTags&#34;功能

searchTags(){

            let req = fetch(url + document.getElementById("tags-input-field").value,
                {
                    method: "GET",
                    headers: {
                        "Authorization": "Token " + this.props.token_reducer.token,
                        "content-type": "application/json"
                    }
                })
        req.then(response => response.json()
        ).then(response => {
            console.log(response)
            this.setState({existingTags:response})
        })
    }

问题:这种方法的问题是,我按下的每个字母都会触发searchTags()。假设我非常快地键入10个字母,然后10个请求开始,这就是挂起我的系统。我该如何处理这个问题?

2 个答案:

答案 0 :(得分:1)

您可以使用setTimeout(fetch, n)之类的内容延迟ajax请求,并在每次按键时清除超时。这导致它仅在停止输入至少n毫秒后才进行搜索。

this.state = {
    searchTimeout: false
}

searchTags(){
    clearTimeout(this.state.searchTimeout);
    let searchTimeout = setTimeout(function() {
        let req = fetch(url + document.getElementById("tags-input-field").value,
                {
                    method: "GET",
                    headers: {
                        "Authorization": "Token " + this.props.token_reducer.token,
                        "content-type": "application/json"
                    }
                })
        req.then(response => response.json()
        ).then(response => {
            console.log(response)
            this.setState({existingTags:response})
        })
    }.bind(this), 500);
    this.setState({searchTimeout});
}

答案 1 :(得分:0)

这是搜索输入的一个非常常见的问题。涵盖常见用例的最简单的解决方案是去除呼叫。

constructor () {
 this.searchTags.bind(this);
 this.debouncedSearch = this.debounce(this.searchTags, 300);
}
debounce = (func, wait = 100) => {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
};

// in render
onChange={this.debouncedSearch}

Lodash还有一个很好的现成debounce

由于您要呈现列表,因此每个列表项还需要add a keyDon't use index as your key,选择一个唯一标识符。

<datalist id='languages'>
  {this.state.existingTags && this.state.existingTags.map((item,i)=>{
    return <option key={item.id} value= {item.name} />
  })}
</datalist>