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

Async data retrieval via input box is one step behind

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

结果列表应在输入框更改时更新。

我正在使用 $.getJSON() 调用维基百科 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

主要错误在于您假设在 changeInputText 函数中调用 setState 会在调用 getWikiData.[=19= 之前更改 inputText ]

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

因此,要修复,请在回调中调用 getWikiData,该回调将在更新新状态时触发。

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