1

根據MDN「您也可以對每個案例執行多個單獨操作,並用逗號分隔它們。」下面的例子工程:React JSX中的條件渲染組件部分

var stop = false, age = 23; 

age > 18 ? (
    alert("1"), 
    alert("2") 
) : (
    stop = true, 
    alert("Sorry, you are much too young!") 
); 

但我似乎無法像在下面看到的那樣做React。我期望顯示「是」和「否」按鈕,但它只顯示「否」按鈕。

return (
    <div className="topcoat-list"> 
    <ul className="topcoat-list__container"> 
    { 
     notes.map(function (note) { 
     var title = note.content.substring(0, note.content.indexOf("\n")); 
title = title || note.content; 
     var toggleDeleteDialogs = this.state.isConfirming && note.id === notepad.selectedId; 
     var disableDelete = this.state.isConfirming && note.id !== notepad.selectedId; 

      return (
      <li key={note.id} onClick={this.onSelectNote.bind(null, note.id)} className="topcoat-list__item"> 
      {title} 

      { 
       toggleDeleteDialogs ? 
       (
       <button key={note.id} onClick={this.deleteThisNote.bind(null, note.id)} className="half">Yes</button>, 
       <button className="half" onClick={this.onCancelDelete}>No</button> 
      ) : (
       <button key={note.id} onClick={this.deleteThisNote.bind(null, note.id)} className="full" disabled={disableDelete ? "disabled" : ""}>Delete Note</button> 
      ) 
      } 

      </li> 

     ); 
     }.bind(this)) 
    } 
    </ul> 
    </div> 
); 

全部標記:https://jsfiddle.net/55fvpcLo/

是我的語法關閉或會這樣更優雅呢?

回答

2

小提琴似乎沒有工作,但我可以重現的行爲。儘管它不會引起Adjacent JSX elements must be wrapped in an enclosing tag錯誤,但我懷疑這可能是它不起作用的原因,因爲相鄰元素實際上就是您正在嘗試執行的操作。

我認爲最簡單的解決方案就是將兩個元素封裝在一個封閉標籤中而不是括號中。

+0

這工作的感謝。我之前遇到過這個問題,但這次我並沒有想到這一點。就像你說的,沒有錯誤產生。 – komplexb 2015-03-13 17:37:22

1

您還可以返回一個JSX組件數組,例如,

{ 
    toggleDeleteDialogs ? 
    [<Button ... />, <Button ... />] : 
    <Button .../> 
} 
+0

很好,我很喜歡這個選項可以防止[divitis](https://duckduckgo.com/?q=divitis)。謝謝。 – komplexb 2015-03-15 23:04:16

1

@Adam Stone是正確的,問題是有相鄰的JSX元素沒有包含在結束標記中。

這就是說,你問最優雅的方式來解決問題。

我做了如下修改代碼:

  • 使用此功能可以選擇性地隱藏JSX元素:

    var hideIfFalse=function(boolean){ 
         return boolean? {} : {display : 'none'}; 
    }; 
    

    您可以使用這樣的:

    <div style={hideIfFalse(toggleDeleteDialogs)} /> 
    
  • 將呈現列表項目的邏輯分成renderChildren方法:

    renderChildren:function(notes,classes){ 
        return notes.map(function (note) { 
        //... 
    
  • 作出DeleteDialog組件。它有它自己的呈現邏輯可重複使用的功能,並分離出來提高了代碼的可讀性:

    var DeleteDialog=React.createClass({ 
        render:function(){ 
        var classes=this.props.classes; 
    
        return <div style={hideIfFalse(this.props.toggleDeleteDialogs)}> 
          <button onClick={this.props.onDelete} className="half"> 
          Yes 
          </button>, 
          <button className="half" onClick={this.props.onCancelDelete}> 
          No 
          </button> 
        </div> 
        } 
    }); 
    
  • 我沒碰classSet邏輯,但不明白什麼是應該做的。

Putting it all together

var hideIfFalse=function(boolean){ 
     return boolean? {} : {display : 'none'}; 
    }; 

    var notepad = { 
     notes: 
     [ 
      { 
       id: 1, 
       content: "Hello, world!\nBoring.\nBoring.\nBoring." 
      }, 
      { 
       id: 2, 
       content: "React is awesome.\nSeriously, it's the greatest." 
      }, 
      { 
       id: 3, 
       content: "Robots are pretty cool.\nRobots are awesome, until they take over." 
      }, 
      { 
       id: 4, 
       content: "Monkeys.\nWho doesn't love monkeys?" 
      } 
     ], 
     selectedId: 1 
    }; 

    var DeleteDialog=React.createClass({ 
     render:function(){ 
     var classes=this.props.classes; 

     return <div style={hideIfFalse(this.props.toggleDeleteDialogs)}> 
       <button onClick={this.props.onDelete} className="half"> 
       Yes 
       </button>, 
       <button className="half" onClick={this.props.onCancelDelete}> 
       No 
       </button> 
     </div> 
     } 

    }) 

    var NotesList = React.createClass({ 
     getInitialState: function() { 
     return { 
      isConfirming: false 
     }; 
     }, 

     onSelectNote: function(id) { 
      notepad.selectedId = id; 
     }, 

     deleteThisNote: function(noteId) { 
     if(this.state.isConfirming) { 
      // actual delete functionality should be here 
      this.setState({isConfirming: false}); 
     } 
     else { 
      this.setState({isConfirming: true}); 
     } 
     }, 

     onCancelDelete: function() { 
     this.setState({ isConfirming: false }); 
     }, 
     renderChildren:function(notes,classes){ 
     return notes.map(function (note) { 
       var title = note.content.substring(0, note.content.indexOf("\n")); 
       title = title || note.content; 
       var toggleDeleteDialogs = this.state.isConfirming && note.id === notepad.selectedId; 
       var disableDelete = this.state.isConfirming && note.id !== notepad.selectedId; 
        return <li key={note.id} 
          onClick={this.onSelectNote.bind(null, note.id)} 
          className="topcoat-list__item"> 
          {title} 
          <button key={note.id} onClick={this.deleteThisNote.bind(null, note.id)} className="full" disabled={disableDelete ? "disabled" : ""}>Delete Note</button> 
          <DeleteDialog 
          toggleDeleteDialogs={toggleDeleteDialogs} 
          note={note} 
          onDelete={this.deleteThisNote.bind(null, note.id)} 
          onCancelDelete={this.onCancelDelete.bind(this)} /> 
         </li> 
       }.bind(this)) 
     }, 

     render: function() { 
     var notes = notepad.notes; 
     var cx = React.addons.classSet; 
     var classes = cx({ 
      "topcoat-button-bar__button": true, 
      "full": !this.state.isConfirming, 
      "half": this.state.isConfirming, 
     }); 

     return (
      <div className="topcoat-list"> 
      <ul className="topcoat-list__container"> 
       {this.renderChildren(notes,classes)} 
      </ul> 
      </div> 
     ); 
     } 
    }); 

    React.render(<NotesList />, document.getElementById('container')); 

的jsfiddle:http://jsfiddle.net/55fvpcLo/2/

+0

感謝撰寫偉大創意。 – komplexb 2015-03-17 17:41:49