2016-06-13 77 views
19

Sto tentando di eseguire il rendering dei componenti in modo condizionale utilizzando il caso switch in React JSX. Sto cercando di costruire qualcosa che legge da una specifica struttura json e rende i dati. Poiché possono esserci molti diversi componenti e dati, sto provando a renderlo in modo dinamico. Guarda il mio codice qui sotto, non ricevo errori ma i componenti non vengono visualizzati. All'interno del mio html, posso solo vedere. Ciò significa che il ciclo non funziona. Ho provato ad usare lo stesso loop in JS vanilla e funziona.Utilizzo di loop e casi di switch in React per il rendering dinamico di diversi componenti

var myPackage = [{ 
    sectionInfo:[{ 
     elementType: 1, 
     text: "This is text from element type 1" 
    }] 
}, 
{ 
    sectionInfo:[{ 
     elementType: 2, 
     text: "This is text from element type 2" 
    }] 
}]; 
var App = React.createClass({ 

    render: function(){ 
     var elements = []; 
     elements = myPackage.map(function(myObj){ 
      myObj.sectionInfo.map(function(myObj1){ 
       switch(myObj1.elementType){ 
        case 1: return(
           <Component1 text = {myObj1.text}/> 
          ); 
          break; 
        case 2: return(
           <Component2 text = {myObj1.text}/> 
          ) 
          break;  
       } 
      }) 
     }); 
     return(
      <div className="App"> 
       {elements} 
      </div> 
     ) 
    } 
}); 
var Component1 = React.createClass({ 
    render:function(){ 
     return(
      <div className = "element1"> 
       {this.props.text} 
      </div> 
     ) 
    } 
}); 
var Component2 = React.createClass({ 
    render:function(){ 
     return(
      <div className = "element2"> 
       {this.props.text} 
      </div> 
     ) 
    } 
}); 
ReactDOM.render(<App/>,document.getElementById('container')); 

Modifica: apportato alcune aggiunte al codice e ora sto affrontando un nuovo problema. Ecco il nuovo codice:

var App = React.createClass({ 

     render: function(){ 
      var elements = []; 
      elements = myPackage.map(function(myObj){ 
       return(
         <div> 
          myObj.sectionInfo.map(function(myObj1){ 
          switch(myObj1.elementType){ 
          case 1: return(
            <Component1 text = {myObj1.text}/> 
           ); 
           break; 
          case 2: return(
            <Component2 text = {myObj1.text}/> 
           ) 
           break;  
         } 
         } 
        </div> 
       ) 
       }); 
     return(
      <div className="App"> 
       {elements} 
      </div> 
     ) 
    } 
}); 

Voglio rendere ogni volta all'interno di un div. In modo che se una sezione ha più di 3 elementi, allora tutti e 3 devono essere all'interno di un div.

+1

'elements' è una Li st of lists ma dovrebbe essere una lista di componenti. Prova ad appiattirlo con 'elements = Array.prototype.concat.apply ([], elements)' –

risposta

15

Si dovrebbe restituire valore dalla prima .map, nel tuo caso è risultato da interno .map

var elements = myPackage.map(function(myObj){ 
    return myObj.sectionInfo.map(function(myObj1) { 
    // ... 
    }); 
}); 

Aggiornamento:

Sulla base della sua nuovo aggiornamento, è possibile modificare il codice come questo

var App = React.createClass({ 

    section: function(myObj, parentIndex) { 
    return myObj.sectionInfo.map(function(myObj1, index) { 
     const key = parentIndex + '.' + index; 

     switch(myObj1.elementType) { 
     case 1: 
      return <Component1 text = {myObj1.text} key={ key } /> 
     case 2: 
      return <Component2 text = {myObj1.text} key={ key } /> 
     } 
    }); 
    }, 

    render: function() { 
    var elements = myPackage.map(function(myObj) { 
     return <div> 
     { this.section(myObj, index) } 
     </div> 
    }, this); 

    return <div className="App"> 
    { elements } 
    </div>; 
    } 
}); 
3

Manca un reso come indicato nello answer by Alexander T, ma consiglierei anche di aggiungere una chiave a ciascuno dei tuoi elementi. Reagire dipende da questo valore per esso è diff'ing algoritmo, si potrebbe fare qualcosa di simile:

render: function(){ 
    var elements = myPackage.map(function(myObj, pIndex){ 
    return myObj.sectionInfo.map(function(myObj1, sIndex){ 
     var key = pIndex + '.' + sIndex;    
     switch(myObj1.elementType) { 
     case 1: return(
      <Component1 key={key} text={myObj1.text}/> 
     ); 
     case 2: return(
      <Component2 key={key} text={myObj1.text}/> 
     ) 
     } 
    }) 
    }); 
    return(
    <div className="App"> 
     {elements} 
    </div> 
) 
} 

Leggi qui per ulteriori informazioni: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children

31

per linea/non creata nuova funzione, è possibile utilizzare in questo modo

<div> 
    {(() => { 
     switch (myObj1.elementType) { 
      case 'pantulan': 
       return <Component1 text = {myObj1.text} key={ key } /> 
      default : 
       null 
     } 
    })()} 
</div> 
+0

È meglio creare una nuova funzione a causa del fatto che nel tuo caso ogni volta che esegue il rendering dell'html verrà riproposto rendere la funzione. Se lo fai in una funzione separata, non lo farà nuovamente. –

40

Per fare un caso interruttore JSX farlo come segue:

{{ 
    sectionA: (
     <SectionAComponent /> 
    ), 
    sectionB: (
     <SectionBComponent /> 
    ), 
    sectionC: (
     <SectionCComponent /> 
    ) 
    }[section]} 
+2

Come gestisce questo valore di default? – Isaac

+0

Sull'ultima riga, puoi fare '[sezione || sectionC] ' per ottenere una copertura migliore, se si desidera che la sezione C sia l'impostazione predefinita. – frandroid

+0

@frandroid l'impostazione predefinita deve andare nella parte superiore dello switch. L'ultima partita nella valutazione top-down è quella che verrà restituita. – Chris