[英]React.js: react on changes in external object
阅读官方react.js文档后,我了解它应该如何以良好的方式工作,例如
如果我使用外部对象作为模型,比如一些全局数组,它应该可用于某些非react.js代码部分,或者将来可以在某个地方使用 Web 套接字进行修改,我该怎么办? 在每个动作之后调用ReactDOM.render是一种好方法吗? AFAIK 从性能的角度来看,它应该可以正常工作。
你仍然使用setState
:
let React = require('React');
let externalThing = require('tools/vendor/whoever/external-lib');
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = this.getInitialState();
}
getInitialState() {
// This assumes your external thing is written by someone who was
// smart enough to not allow direct manipulation (because JS has
// no way to monitor primitives for changes), and made sure
// to offer API functions that allow for event handling etc.
externalThing.registerChangeListener(() => this.updateBasedOnChanges(externalThing));
return { data: externalThing.data }
}
updateBasedOnChanges(externalThing) {
// note that setState does NOT automatically trigger render(),
// because React is smarter than that. It will only trigger
// render() if it sees that this new 'data' is different
// (either by being a different thing entirely, or having
// different content)
this.setState({
data: externalThing.data
});
}
render() {
// ...
}
}
如果你使用的外部东西写得很糟糕,你必须直接操作它的数据,你的第一步是为它编写一个 API,这样你就不会直接操作这些数据。
let externalData = require('externaldata') // example: this is a shared array
let ExternalDataAPI = new ExternalDataAPI(externalData);
...
然后确保 API 具有所有更新和事件挂钩:
class ExternalDataAPI {
constructor(data) {
this.data = data;
this.listeners = [];
}
addListener(fn) {
this.listeners.push(fn);
}
update(...) {
// do something with data
this.listeners.forEach(fn => fn());
}
...
}
或者,有些框架已经为您执行了此操作(flux 等),但它们也在某种程度上决定了“应该完成”多少事情,因此这可能对您的需求来说太过分了。
由于您的问题是以可管理的方式组织代码,因此我首先建议将 ReactJS 与 Flux 类型的框架(如 Redux 或 Relay)配对。
如果您现在想跳过它,那么您可以使用层次结构顶部的一些反应组件来组织您的项目,以存储和检索数据。 例如,在这样的组件中,在它的componentWillMount方法中,您可以启动一个setTimeout
,它会定期检查您的全局数组并在适当的时候调用setState
。 然后 render 方法应该包含接收这个状态作为 props 的子组件。
下面是一个例子。 显然,计时器可以被您用来订阅数据更改的任何方法替换。
// your global object var globalState = {name: "Sherlock Holmes"} function onData(callback) { setInterval(function(){ callback(globalState) }, 1500) } var Child = React.createClass({ render: function() { return <h1>Hello, {this.props.name}</h1>; } }); var Root = React.createClass({ getInitialState: function() { return {} }, componentWillMount: function() { var that = this; this.props.onData(function(data){ that.setState({external: data}) }) }, render: function() { if (this.state.external) return <Child name={this.state.external.name}/> else return <div>loading...</div>; } }); ReactDOM .render(<Root onData={onData} />, document.getElementById('container'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.