2015-07-11 61 views
1

雖然嘗試ReactJs,我對着下面的設計問題:ReactJs,產生事件reactjs應用程序之外

下面就是我試圖模擬一個聊天應用一個簡單的HTML,我目前正在建設的名單在線成員並試圖找出將新成員添加到列表中的代碼。

下面的React應用程序由它們的DOM層次結構中的以下類組成。

ChatApp>會員>會員

在反應類ChatApp,我可以用setInterval來更新成員收集並生成一個新成員新的DOM,但現在我想從外面的嘗試同樣的ChatApp類。

因此,我添加了一個按鈕「添加成員」,並希望調用它的點擊功能,然後將新成員添加到列表中。

但是,我應該如何從反應應用程序的外部獲取反應ChatApp及其setState方法的實例?

<html> 

<head> 

    <style> 
     .onlineList{ 
      width:300px; 
      height:500px; 
      display:inline-block; 
      overflow:auto; 
      border:1px solid lightgray; 
     } 

     .onlineList a{ 
      display:inline-block; 
      width:100%; 
      padding:10px; 
      box-sizing:border-box; 
      text-decoration:none; 
      color:gray; 
      font-weight:bold; 
      border-top:1px solid lightgray; 
      border-bottom:1px solid lightgray; 
     } 
     .onlineList a:hover{ 
      color:black; 
      background-color:lightgray; 
     } 

    </style> 

    <script src="js/jquery-1.11.3.min.js"></script> 
    <script src="js/react-with-addons.js"></script> 
    <script src="js/JSXTransformer.js"></script> 

    <script> 
     function addNewMember(){ 
      // How can the setState in chatApp react class be called from here? 
     } 
    </script> 

    </head> 

<body> 
    <button onClick="addNewMember()">Add New Member</button> 
    <div id="chatApp"></div> 
    <script type="text/jsx"> 
     var Member = React.createClass({ 
      render: function() { 
       return <a href='#'>{this.props.memberInfo}</a>; 
      } 
     }); 

     var MemberList = React.createClass({ 
      render: function(){ 
       var membersDOM = []; 
       for(var m=0; m < this.props.members.length;m++){ 
        membersDOM.push(<Member memberInfo={this.props.members[m].name}/>); 
       } 
       return (
        <div id='onlineList' className={'onlineList'}>{membersDOM}</div> 
       ) 
      } 
     }); 

     var ChatApp = React.createClass({ 
      getInitialState: function(){ 
       var members = { 
        members: [] 
       }; 
       for(var m=0;m<1;m++){ 
        members.members.push({name: m + 1}); 
       }; 

/*    setInterval(function(){ 
        members.members.push({name: members.members.length + 1 }); 
        this.setState(members); 
       }.bind(this),2000); 
*/ 
       return members; 
      }, 
      render: function(){ 
       return (
        <div id='container'> 
         <MemberList members={this.state.members}/> 
        </div> 
       ) 
      } 
     }) 

     React.render(
      <ChatApp/>, 
      document.getElementById('chatApp') 
     ); 

    </script> 
</body> 


</html> 
+1

如果您使用React,您應該也可以使用Flux應用程序架構,它被設計爲與React的反應式渲染一起工作。查看https://facebook.github.io/flux/docs/overview.html。基本上,你會根據商店的數據來渲染你的組件。當添加成員被點擊時,您分派一個動作來更新商店,然後更新反應組件。 – Hans

+0

@Hans,哦,好吧,我會看看那個。 – codin

回答

1

你永遠應該設置組件之外的組件的狀態。

應將React應用程序設置爲組件的層次結構,頂層組件管理子組件的狀態。因此,如果您想要在ChatApp之外使用此功能,則需要將按鈕移至父組件,以及要修改的狀態和addNewMember處理程序。然後,您將通過ChatApp將該狀態作爲props,就像您目前使用MemberList一樣。

話雖這麼說,沒有任何理由,爲什麼你不能只是包括ChatApp按鈕和addNewMember

addNewMember: function (e) { 
    e.preventDefault(); 

    var name = this.state.members.length + 1; 
    var members = this.state.members; 

    this.setState({ 
    members: members.concat([{name: name}]) 
    }); 
}, 

render: function(){ 
    return (
    <div> 
     <button onClick={this.addNewMember}>Add New Member</button> 
     <div id='container'> 
     <MemberList members={this.state.members}/> 
     </div> 
    </div> 
) 
} 

而且,這是不直接關係到你的問題,但你不應該叫setState in getInitialState。它的目的是簡單地實例化組件的狀態,因爲它在組件被渲染之前調用一次,並且不像其他生命週期方法那樣觸發重新渲染。

所以在你的例子中,你只會返回一個空的members數組。然後,如果要將memberssetInterval,setTimeout或任何異步過程相加,您可以在componentDidMount中這樣做。使用上面addNewMember,它會是這個樣子(確保如果你運行它佔e):

getInitialState: function() { 
    return { 
    members: [] 
    }; 
}, 

componentDidMount: function() { 
    setInterval(this.addNewMember, 2000); 
} 

無論如何,我希望這會有所幫助。有問題儘管問我。我很樂意詳細介紹構建更復雜的React應用程序和最佳實踐。

+0

謝謝,詳細解釋。 我想嘗試應用程序外部的'添加'按鈕,因爲我假定已經開發的頁面具有用jquery編寫的一些動態部分的場景,該頁面獲取從頁面中其他位置生成的事件/數據的更新。 現在,如果將該部分替換爲反應組件,並且對事件/數據生成機制沒有/很少進行更改,那麼整個事情將如何工作。 這可能並不實際,但我只是想知道。 – codin

+0

@codin我不知道我明白你在問什麼。請提供更多詳細信息... –

+0

沒關係這個問題,我相信我應該專注於理解現在的反應更好。謝謝! – codin