2016-02-26 55 views
1

在用Redux,flux和其他pub/sub方法掙扎太多之後,我用以下技術結束了。我不知道這是否會造成一些大的損害或缺陷,因此將其張貼在此處,以便從有經驗的程序員那裏瞭解其優點和缺點。Reactjs組件之間的通信

var thisManager = function(){ 

    var _Manager = []; 
    return{ 
     getThis : function(key){ 
      return _Manager[key]; 
     }, 
     setThis : function(obj){    
      _Manager[obj.key] = obj.value; 
     } 
    } 
}; 
var _thisManager = new thisManager(); 

// React Component 
class Header extends Component{ 
    constructor(){ 
     super(); 
     _thisManager.setThis({ key: "Header", value:this} 
    } 
    someFunction(data){ 
     // call this.setState here with new data. 
    } 
    render(){ 
     return <div /> 
    } 
} 

// Then from any other component living far somewhere you can pass the data to the render function and it works out of the box. 
i.e. 

class Footer extends Component{ 
    _click(e){ 
    let Header = _thisManager.getThis('Header'); 
    Header.somefunction(" Wow some new data from footer event "); 
    } 
render(){ 
     return(
     <div> 
      <button onClick={this._click.bind(this)}> send data to header and call its render </button> 
     </div> 


    ); 
    } 
} 

我送JSON在我的應用程序中的數據並將其完美呈現所需的成分,我可以調用渲染沒有任何的pub/sub或深傳承道具來調用父類的方法以改變該.setState導致重新渲染。

到目前爲止,該應用程序工作正常,我也愛它的簡單了。請扔光這種技術的優點和缺點

問候

編輯:

它是壞的調用渲染,所以我改成了另一種方法來獲得這種設置的更多優點和缺點。與此設置

+1

儘管這種方式在一個非常有限的用例(如您提供的示例)中起作用,但會干擾反應組件的生命週期。渲染方法決不是直接調用,也不應該有輸入,這使得它不純。至少,揭露一種不同的公共方法,它接受你發送的任何內容。在該方法中,執行setState將隱式地調用渲染。最後,而不是渲染調用該方法。 – hazardous

+0

謝謝@HazardouS,肯定是正確的,但技術怎麼樣,基本上我沒有公開它是可以調用渲染的引用,我猜setState會做同樣的效果加上什麼損壞的部分發送數據渲染函數作爲參數? –

+0

SO應用程序不是很好的長期解釋:)。請閱讀React中的純渲染方法假設。 React批處理渲染,這就是爲什麼它不應該直接調用。 – hazardous

回答

1

兩個主要關注點:
1.你不應該做出響應的生命週期方法直接
2.後門進入組件是一個壞主意,這破壞反應的可維護性

廣告1 : 如果您直接調用render()(或任何其他反應方法),則可能不會在組件樹中調用componentDidMount(),componentDidUpdate()和其他生命週期方法。

危險是:

  • 許多設計與反應成分在很大程度上依賴於生命週期方法被解僱:getInitialState()componentWillReceiveProps()shouldComponentUpdate()componentDidMount(),等等等等,如果你直接調用render(),許多組件可能會破壞或顯示奇怪的行爲。
  • 您冒着破壞反應的差異引擎的風險:通過生命週期管理,反應在其內部存儲器中保留虛擬副本。爲了正確工作,如果對反應的工作至關重要,則該副本的完整性。

更好的方式是(但仍然違反了我的第二個點):

  • 包括組件內的不同方法。
  • 如果要重新渲染,其中有一個setState()
  • 並從外部調用該方法。

廣告2. 的直接引用一個安裝部件(作爲thisManager確實)具有一些額外的風險。 React的設計和侷限性是有原因的:保持道具和狀態的單向流和組件層次結構,使事情易於維護。

如果你打破這種模式 - 通過在組件中構建後門,允許操縱狀態 - 你打破了這種設計原則的反應。這是一個快速的捷徑,但是當您的應用程序增長時肯定會造成很大的痛苦和沮喪。

據我所知,此規則的唯一可接受的例外是:

一個組件內
  • 中的方法,以Ajax調用的結果作出反應,更新狀態
  • (如獲取來自服務器的數據後)一個組件內的方法來處理(在形式,例如運行驗證一個孩子按鈕被點擊後)從它的直接後代子組件觸發

所以,如果你想使用它的目的,那麼你應該罰款。 警告字:標準反應方法警衛隨機訪問組件,因爲調用組件或方法需要引用組件。在這兩個例子中,這樣的參考是可用的。
在你的設置中,任何一段外部代碼都可以查找表格中「標題」的引用,並調用更新狀態的方法。 有了這樣的間接引用,並且沒有辦法告訴哪個源實際稱爲你的組件,你的代碼很可能變得更難以調試/維護。

+0

感謝@wintvelt,所以任何其他方法,只是可以造成this.setState將罰款? –

+0

不完全,請參閱我的第二點。 – wintvelt

+0

正確的感謝,我編輯了這個問題,現在想知道爲什麼會這樣做,因爲我基本上我想要的是用新的數據重新組件,所以最後一件事就是訂閱一些事件並做它,因爲我發現容易的是然後發佈一個事件我發送數據直接到我的功能,可以做到這一點.setState?你說什麼? –