簡體   English   中英

React.js:對外部對象的變化做出反應

[英]React.js: react on changes in external object

閱讀官方react.js文檔后,我了解它應該如何以良好的方式工作,例如

  1. 我有處於初始組件狀態的項目列表
  2. 通過setState添加新項目將更新狀態並觸發 UI 更新

如果我使用外部對象作為模型,比如一些全局數組,它應該可用於某些非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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM