通过输入框检索异步数据落后了一步

Posted

技术标签:

【中文标题】通过输入框检索异步数据落后了一步【英文标题】:Async data retrieval via input box is one step behind 【发布时间】:2016-03-26 22:56:22 【问题描述】:

我正在根据用户的输入制作一个简单的***结果查看器。

只要输入框发生变化,结果列表就会更新。

我正在使用 $.getJSON() 来调用 Wikipedia API。但是,无论何时更改输入框,我的结果列表都不会更新。事实上,它似乎落后了一步,所以在更新状态方面肯定有一些我不理解的东西,特别是在异步调用中。

话虽如此,响应确实发生了变化,正如我在控制台中看到的那样,所以在结果列表的呈现中发生了一些我不理解的事情。

从 React 调试工具和控制台,我可以看到我的数组正在按预期更新,如下所示:

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Wiki Searcher</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <script src="script.js"></script>
</body>
</html>

Javascript

var SearchBox = React.createClass(

    changeText: function () 
        this.props.changeInputText(ReactDOM.findDOMNode(this.refs.searchBox).value);
    ,

    render: function () 
        return (
            <input type="text" onChange=this.changeText ref="searchBox"/>
        )
    
);

var SearchItemList = React.createClass(

    render: function () 

        console.log('data:', this.props.results);
        console.log('inputtext', this.props.inputText);

        var listItems = this.props.results
            .filter(function (e, i) 
                return e.title.indexOf(this.props.inputText) !== -1;
            .bind(this))
            .map(function (e, i) 
            return (
                <li key=i>
                    <a href="#"><h3>e.title</h3></a>
                    <p>e.snippet</p>
                </li>
            )
        );
        return (
            <ul>
                listItems
            </ul>
        )
    
);
//TODO: extract list item into its own component?
var Main = React.createClass(

    getInitialState: function () 
        return 
            inputText: 'javascript',
            results: [],
        
    ,

    getWikiData: function () 

        var prependage = 'https://en.wikipedia.org/w/api.php?action=query&list=search&format=json&srsearch='
        var appendage = "&callback=?";
        var url = prependage + this.state.inputText + appendage;

        $.getJSON(url, function (data) 
            this.setState(
                results: data.query.search
            );
        .bind(this));
    ,

    componentDidMount: function () 
        this.getWikiData();
    ,

    changeInputText: function (searchTerm) 
        this.setState(
            inputText: searchTerm,
        );
        this.getWikiData();
    ,

    render: function () 
        return (
            <div className="container">
                <div className="col-sm-8 col-sm-offset-2">
                    <h1>Wiki Searcher</h1>
                    <SearchBox inputText=this.state.inputText changeInputText=this.changeInputText/>
                    <SearchItemList results=this.state.results inputText=this.state.inputText/>
                </div>
            </div>
        )
    
);

ReactDOM.render(<Main/>, document.getElementById('container'));

Plunkr

【问题讨论】:

顺便说一句,工作人员和所有工作人员的好问题。 【参考方案1】:

主要错误在于您假设在您的changeInputText 函数中调用setState 会在您调用getWikiData 之前更改inputText

setState 是一个异步函数,因此当您的getWikiData 触发时,inputText 的新值可能不会被设置。

所以要修复,请在回调中调用getWikiData,当新状态更新时将触发。

changeInputText: function (searchTerm) 
    this.setState(
        inputText: searchTerm,
    , () => 
       this.getWikiData();
    );  
,

【讨论】:

谢谢你,它帮助我更多地了解setState()。但是,我仍然无法填充我的列表。它似乎不再“落后一步”,但它确实选择了何时填充列表。例如,查询ton 生成了一个列表,但tony 没有出现任何内容。有什么想法吗?

以上是关于通过输入框检索异步数据落后了一步的主要内容,如果未能解决你的问题,请参考以下文章

如何从 GUI 中的编辑框中检索数据

在下拉框输入值的时候,下拉框中的值出现在下拉框中,怎么实现?

检索框/输入框测测试用例

Selenium 查找节点

前嗅ForeSpider教程:通过搜索框检索关键词采集数据

用jquery怎么检索表格里的内容与文本输入框的里内容是不是相等,相等的话数据所在的行变颜色显示