Ответ 1
setState
выполняет обратный вызов, который позволяет гарантировать, что this.loadGroupsFromQuery()
вызывается только после обновления this.state
.
this.setState({...}, function() {
this.loadGroupsFromQuery();
});
Я пытаюсь выполнить ReactJS, но мне сложно интегрировать его в мою форму. Я создаю форму для автоматического предложения в ReactJS. В моем onChangeQuery
я устанавливаю состояние, а затем вызываю функцию AJAX, чтобы захватывать предложения из моего кода на стороне сервера; однако я заметил, что
loadGroupsFromServer
функция не получает последнее состояние... Это один ключевой ход слишком медленный. Я знаю, что setState не мгновен, но зачем мне использовать setState для моих форм? Лучше ли использовать ссылки? Лучше просто получить значение из e.target.value?
Help!
var GroupForm = React.createClass({
getInitialState: function() {
return {query: "", groups: []}
},
componentDidMount: function () {
this.loadGroupsFromServer();
},
loadGroupsFromServer: function () {
$.ajax({
type: "GET",
url: this.props.url,
data: {q: this.state.query},
dataType: 'json',
success: function (groups) {
this.setState({groups: groups});
}.bind(this),
error: function (xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
onChangeQuery: function(e) {
this.setState({query: e.target.value})
this.loadGroupsFromServer();
},
render: function() {
return (
<div>
<form class="form form-horizontal">
<div class="col-lg-12">
<input type="text" className="form-control" value={this.state.query} placeholder="Search for groups" onChange={this.onChangeQuery} />
</div>
</form>
<GroupList groups={this.state.groups} />
</div>
)
}
})
setState
выполняет обратный вызов, который позволяет гарантировать, что this.loadGroupsFromQuery()
вызывается только после обновления this.state
.
this.setState({...}, function() {
this.loadGroupsFromQuery();
});
loadGroupsFromServer должен принимать аргумент запроса.
componentDidMount: function () {
this.loadGroupsFromServer(this.state.query);
},
loadGroupsFromServer: function (query) {
$.ajax({
/* ... */
data: {q: query},
/* ... */
});
},
onChangeQuery: function(e) {
this.setState({query: e.target.value})
this.loadGroupsFromServer(e.target.value);
},
Обычно вы должны пытаться уменьшить доступ к состоянию, потому что это дает вам большую гибкость.
В зависимости от случая вам может потребоваться дождаться обновления компонента перед выполнением некоторых действий:
onChangeQuery: function(e) {
this.setState({query: e.target.value}, function(){
this.loadGroupsFromServer(this.state.query)
}.bind(this));
},
Или вы можете переписать его вот так, что, по моему мнению, является более чистым.
onChangeQuery: function(e) {
this.setState({query: e.target.value});
},
componentWillUpdate: function(nextProps, nextState){
// optionally perform better heuristics, but this prevents them pressing space
// from triggering an update
if (nextState.query.trim() !== this.state.query.trim()) {
this.loadGroupsFromServer(nextState.query);
}
}
setState Best Practice
ES5
this.setState(function(state){
state.query= e.target.value;
}, function()=>{
//after callback
});
ES6
this.setState(state => {
state.query= e.target.value;
}, ()=>{
//after callback
});
Основной причиной проблемы с одним символом было то, что вы читали состояние до его установки. setState работает быстро, но не мгновенно и синхронно. Предыдущие ответы предоставляют вам пару способов рефакторинга.
setState не медленный, но он асинхронный. Таким образом, как и в предыдущем ответе, он будет работать синхронно, пока ваше состояние не будет установлено.
В соответствии с наилучшей практикой состояние должно быть установлено на стороне метода рендеринга.