2017-12-27 1 views
0

Ich versuche Elemente von JSON zu laden und dropdown div mit Beschreibung bei Klick umzuschalten. Während ich Elemente sequentiell (zB: loc1 & desc1, loc2 & desc2) auf statischen Divs anzeigen kann, habe ich Probleme herauszufinden, wie man es korrekt rendert, wenn der zweite Teil (desc) ausgeblendet ist und nur angezeigt wird, wenn auf das loc div geklickt wird.ReactJS: Wie man JSON Elemente sequentiell abbildet und das versteckte div beim Klick zeigt

Was wäre der beste Weg, das Ergebnis zuzuordnen, so dass es nicht als loc1 & loc2, desc1 & desc2 sondern als loc1 & desc1, loc2 & desc2 angezeigt wird?

Code:

var places = { 
    library: { 
    location: [ 
     { 
     loc_name: "library1", 
     "desc": "desc1 : Modern and spacious building" 
     }, 
     { 
     loc_name: "library2", 
     "desc": "desc2 : A cosy small building" 
     } 
    ] 
    } 
}; 



function contentClass(isShow) { 
    if (isShow) { 
    return "content"; 
    } 
    return "content invisible"; 
} 

class Toggle extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { isShow: false }; 
    this.handleClick = this.handleClick.bind(this); 
    } 

    handleClick() { 
    this.setState(function (prevState) { 
     return { isShow: !prevState.isShow }; 
    }); 
    } 

    render() { 

    const libraries_desc = places.library.location.map((libr) => 
     <div> 
     <p>{libr.desc}</p> 
     </div> 
    ); 
    const lib_names = places.library.location.map((libr) => 
     <div> 
     <p>{libr.loc_name}</p> 
     </div> 
    ); 

    return (
     <div> 
     <div className='control' onClick={this.handleClick}> 
      <h4>{lib_names}</h4> 
      <div className={contentClass(this.state.isShow)}>{libraries_desc}</div> 
     </div> 
     </div> 
    ); 
    } 
} 



render((
    <Toggle /> 
), document.getElementById('root')); 

Aktuelles Ergebnis:

library1 
library2 
desc1 : Modern and spacious building 
desc 2 : A cosy small building 

Gewünschtes Ergebnis:

library1 
desc1 : Modern and spacious building (hidden but shown when clicked) 

library2 
desc 2 : A cosy small building (hidden but shown when clicked) 

Codesandbox

Antwort

1

Ich könnte versuchen, einen Standort in eine separate Komponente zu extrahieren. Durch das Extrahieren ist jeder Ort für die Kenntnis seines Zustands verantwortlich. In Ihrem Fall bedeutet das seine Sichtbarkeit (gesteuert von this.state.isShow).

Hier ist, wie Sie es tun könnte:

import React from 'react'; 
import { render } from 'react-dom'; 

var places = { 
    library: { 
    location: [ 
     { 
     loc_name: "library1", 
     "desc": "Modern and spacious building" 
     }, 
     { 
     loc_name: "library2", 
     "desc": "A cosy small building" 
     } 
    ] 
    } 
}; 

class Location extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { isShow: false }; 
    this.handleClick = this.handleClick.bind(this); 
    } 

    handleClick() { 
    this.setState(function (prevState) { 
     return { isShow: !prevState.isShow }; 
    }); 
    } 

    contentClass(isShow) { 
    if (isShow) { 
     return "content"; 
    } 
    return "content invisible"; 
    } 

    render() { 
    return (
     <div className='control' onClick={this.handleClick}> 
     <h4>{this.props.desc}</h4> 
     <div className={this.contentClass(this.state.isShow)}>{this.props.loc_name}</div> 
     </div> 
    ) 
    } 
} 

class Toggle extends React.Component { 
    constructor(props) { 
    super(props); 
    } 

    render() { 
    const locations = places.library.location.map(location => { 
     return <Location {...location} /> 
    }) 

    return (
     <div> 
     {locations} 
     </div> 
    ); 
    } 
} 



render((
    <Toggle /> 
), document.getElementById('root')); 
1

Ihre Toggle Komponente sollte b Das ist so.

class Toggle extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     isShow: false, 
     id: -1, // initial value 
    }; 
    } 

    handleClick = (id) => { 
    this.setState({ 
     isShow: !this.state.isShow, 
     id: id 
    }); 
    } 

    render() { 
    const { location } = places.library; 
    const { isShow, id } = this.state; 
    return (
     <div className="control"> 
      {location.map((libr, index) => (
      <div key={index} onClick={() => { this.handleClick(index) }}> 
       <p>{libr.loc_name}</p> 
       {(isShow && (id === index)) && <p>{libr.desc}</p>} 
      </div> 
      ))} 
     </div> 
    ); 
    } 
} 

Also, wenn Sie auf dem div Element klicken. Ein Klickereignis wird ausgelöst, das handleClick aufgerufen wird, das die index als Parameter an die Funktion übergeben wird. Das setzt isShow auf false oder truth und umgekehrt zusammen mit dem aktuellen Element, das angezeigt werden soll, welches durch this.state.id ausgewählt wird. Also immer isShow ist wahr und this.state.id entspricht index Element des Arrays. Ihre Beschreibung zeigt andernfalls, dass sie ausgeblendet wird, wie Sie möchten.

So wird Ihr gewünschtes Ergebnis in etwa so sein.

library1 
desc1 : Modern and spacious building (hidden but shown when clicked) 

library2 
desc 2 : A cosy small building (hidden but shown when clicked) 
+0

Es ist auf Endtag location.map einen Syntaxfehler zeigt ((libr, Index), auch wenn es richtig zu schließen ist, warum das so sein würde – Amma

+0

es.? fehlte ein '(' am Ende von. map() Ich habe es behoben. guck mal wieder den Code in render methid –

+1

Das wars - jetzt klappt es, danke! – Amma

Verwandte Themen