轮询在 React JS mixin 中不起作用
Polling not working in React JS mixin
所以我创建了以下 mixin:
var Polling = {
startPolling: function() {
var self = this;
setTimeout(function() {
self.poll();
if (!self.isMounted()) {
return;
}
self._timer = setInterval(self.poll(), 15000);
}, 1000);
},
poll: function() {
if (!this.isMounted()) {
return;
}
var self = this;
console.log('hello');
$.get(this.props.source, function(result) {
if (self.isMounted()) {
self.setState({
error: false,
error_message: '',
users: result
});
}
}).fail(function(response) {
self.setState({
error: true,
error_message: response.statusText
});
});
}
}
注意poll
函数中的console.log('hello');
。按照这个逻辑,我应该每15秒看到一次。
现在让我们看一个 React 组件:
//= require ../../mixins/common/polling.js
//= require ../../mixins/common/state_handler.js
//= require ../../components/recent_signups/user_list.js
var RecentSignups = React.createClass({
mixins: [Polling, StateHandler],
getInitialState: function() {
return {
users: null,
error_message: '',
error: false
}
},
componentDidMount: function() {
this.startPolling();
},
componentWillUnmount: function() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
},
shouldComponentUpdate: function(nextProps, nextState) {
if (this.state.users !== nextState.users ||
this.state.error !== nextState.error ||
this.state.error_message !== nextState.error_message) {
return true;
}
return false;
},
renderContents: function() {
if (this.state.users === null) {
return;
}
return (
<div>
<ul>
<UserList users={this.state.users} />
</ul>
</div>
);
},
render: function() {
return (
<div>
{this.loading()}
{this.errorMessage()}
{this.renderContents()}
</div>
)
}
});
RecentSignupsElement = document.getElementById("recent-signups");
if (RecentSignupsElement !== null) {
ReactDOM.render(
<RecentSignups source={ "http://" + location.hostname + "/api/v1/recent-signups/" } />,
RecentSignupsElement
);
}
这里我们看到在我调用的componetDidMount
函数中this.startPolling
当页面加载时,1秒后我看到的是:
hello
hello
- A) 它的(
poll
函数)被调用两次 oO.
- B) 它的(
poll
函数)再也不会被调用了。
我将轮询分开的原因是我可以在同一页面上的其他组件中使用它而不是重复代码。
非常简单的问题:
为什么以及如何解决这个问题?我需要它每 15 秒轮询一次,我应该只在第一次调用 poll
时看到一次 hello
。
在这一行中调用 self.poll(),结果将是计时器:
self._timer = setInterval(self.poll(), 15000);
改为传递函数:
self._timer = setInterval(self.poll, 15000);
作为另一个选项,本着 "you're code's not working? just use someone else's instead!" 的精神,react-async-poll 是一个方便的组件包装器,可用于轮询。
所以我创建了以下 mixin:
var Polling = {
startPolling: function() {
var self = this;
setTimeout(function() {
self.poll();
if (!self.isMounted()) {
return;
}
self._timer = setInterval(self.poll(), 15000);
}, 1000);
},
poll: function() {
if (!this.isMounted()) {
return;
}
var self = this;
console.log('hello');
$.get(this.props.source, function(result) {
if (self.isMounted()) {
self.setState({
error: false,
error_message: '',
users: result
});
}
}).fail(function(response) {
self.setState({
error: true,
error_message: response.statusText
});
});
}
}
注意poll
函数中的console.log('hello');
。按照这个逻辑,我应该每15秒看到一次。
现在让我们看一个 React 组件:
//= require ../../mixins/common/polling.js
//= require ../../mixins/common/state_handler.js
//= require ../../components/recent_signups/user_list.js
var RecentSignups = React.createClass({
mixins: [Polling, StateHandler],
getInitialState: function() {
return {
users: null,
error_message: '',
error: false
}
},
componentDidMount: function() {
this.startPolling();
},
componentWillUnmount: function() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
},
shouldComponentUpdate: function(nextProps, nextState) {
if (this.state.users !== nextState.users ||
this.state.error !== nextState.error ||
this.state.error_message !== nextState.error_message) {
return true;
}
return false;
},
renderContents: function() {
if (this.state.users === null) {
return;
}
return (
<div>
<ul>
<UserList users={this.state.users} />
</ul>
</div>
);
},
render: function() {
return (
<div>
{this.loading()}
{this.errorMessage()}
{this.renderContents()}
</div>
)
}
});
RecentSignupsElement = document.getElementById("recent-signups");
if (RecentSignupsElement !== null) {
ReactDOM.render(
<RecentSignups source={ "http://" + location.hostname + "/api/v1/recent-signups/" } />,
RecentSignupsElement
);
}
这里我们看到在我调用的componetDidMount
函数中this.startPolling
当页面加载时,1秒后我看到的是:
hello
hello
- A) 它的(
poll
函数)被调用两次 oO. - B) 它的(
poll
函数)再也不会被调用了。
我将轮询分开的原因是我可以在同一页面上的其他组件中使用它而不是重复代码。
非常简单的问题:
为什么以及如何解决这个问题?我需要它每 15 秒轮询一次,我应该只在第一次调用 poll
时看到一次 hello
。
在这一行中调用 self.poll(),结果将是计时器:
self._timer = setInterval(self.poll(), 15000);
改为传递函数:
self._timer = setInterval(self.poll, 15000);
作为另一个选项,本着 "you're code's not working? just use someone else's instead!" 的精神,react-async-poll 是一个方便的组件包装器,可用于轮询。