通过输入框进行异步数据检索落后了一步
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'));
主要错误在于您假设在 changeInputText
函数中调用 setState
会在调用 getWikiData
.[=19= 之前更改 inputText
]
setState
是一个异步函数,因此当您的 getWikiData
触发时,可能不会设置 inputText
的新值。
因此,要修复,请在回调中调用 getWikiData
,该回调将在更新新状态时触发。
changeInputText: function (searchTerm) {
this.setState({
inputText: searchTerm,
}, () => {
this.getWikiData();
});
},
我正在根据用户的输入制作一个简单的维基百科结果查看器。
结果列表应在输入框更改时更新。
我正在使用 $.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'));
主要错误在于您假设在 changeInputText
函数中调用 setState
会在调用 getWikiData
.[=19= 之前更改 inputText
]
setState
是一个异步函数,因此当您的 getWikiData
触发时,可能不会设置 inputText
的新值。
因此,要修复,请在回调中调用 getWikiData
,该回调将在更新新状态时触发。
changeInputText: function (searchTerm) {
this.setState({
inputText: searchTerm,
}, () => {
this.getWikiData();
});
},