0
votes

i'm using React to create an App where i can see the flags and various infos about every country. I'm using an API to fetch the data and i've already mapped them all with a grid. That's my code so far:

class App extends React.Component{
  constructor (props){
    super (props);
    this.state={
      countries : [],
      info: ""

    }
  }

  componentDidMount(){
    axios.get(`https://restcountries.eu/rest/v2/all`)
    .then(res => {
      const data = res.data;
      console.log(data);

      this.setState({
        countries : data

      })

this.showInfo = this.showInfo.bind(this)

    })

  }

  showInfo (e) {
   console.log(e.target.key);


  }


  render() {


    return (
      <div className="container">
      {this.state.countries.map(country=>

        <Country name={country.name}
                 key={country.name} 
                 population ={country.population} 
                 region={country.region}
                 capital={country.capital}
                 flag={country.flag}
                 showInfo={this.showInfo}
                 />

      )}
      </div>
    )
  }
}

export default App;

And this is my Country-item component:

const Country = ({name, population, region, capital, flag, showInfo})=>{
    return (
        <div onClick={showInfo} className="country-item">

           <div className="img">
               <img src={flag}/>
               </div> 
            <p>{name}</p>
            <p>population: {population}</p>
            <p>Region: {region}</p>
            <p>Capital: {capital}</p>

        </div>
    )
}

export default Country

So far for now i have something like this: enter image description here

Now i would like to click on each country box item and display that clicked data inside a modal popUp. If i create a modal and i will map it, of course on click i will have all of them displayed in once. how can i pass the props of that box i clicked on the modal component? i created a function trying to capture for example the key props, but i didn't suceed. What's the best strategy? thank you very much for the help

2

2 Answers

0
votes

Attach an onClick handler to each country. When it's clicked, save the country name to the state of the containing component. Render the modal with content only from the country clicked:

class App extends React.Component{
  constructor (props){
    super (props);
    this.state={
      countries : [],
      info: "",
      clicked: ''
    }

    this.countryClickHandler = e => {
      this.setState({clicked: country.name}, () => {
        window.addEventListener('click', this.closeCountryPopup)
      })
    }
    this.closeCountryPopup = e => {
      this.setState({clicked: ''}, () => {
        window.removeEventListener('click', this.closeCountryPopup)
      })
    }
  }

  componentDidMount(){
    axios.get(`https://restcountries.eu/rest/v2/all`)
    .then(res => {
      this.setState({
        countries : res.data
      })
    })
  }

  renderPopup() {
    // if the clicked flag is falsy, null, or an empty string, don't render anything
    if(!this.state.clicked || this.state.clicked === null || !this.state.clicked.length) return null

    // otherwise, render the only clicked country by filtering it by matching it with the string in the state
    const clickedCountry = this.state.countries.find(country => country.name === this.state.clicked)
    return (
      <div className="popup_container">
        <Country 
            name={clickedCountry.name}
            key={clickedCountry.name} 
            population ={clickedCountry.population} 
            region={clickedCountry.region}
            capital={clickedCountry.capital}
            flag={clickedCountry.flag}
          />
      </div>
    )
  }


  render() {
    return (
      <div className="container">
      {this.state.countries.map(country =>
        <div onClick={this.countryClickHandler}>
          <Country 
            name={country.name}
            key={country.name} 
            population ={country.population} 
            region={country.region}
            capital={country.capital}
            flag={country.flag}
          />
       </div>

      )}
      { this.renderPopup() }
      </div>
    )
  }
}

export default App;
0
votes

Your App component should maintain the state of which country should be displayed in a modal. More specifically App component will save in it's state if a modal should be displayed and which country to be displayed in the modal.

The showInfo prop that you pass to the Country component, should notify App component when a country is clicked.

I have created a representative example on CodePen.

class App extends React.Component {
    constructor () {
            super();
            this.state = {
              showModal: false,
              selectedCountry: {},
              countries: [
                  {name: "Germany", continent: "Europe"},
                  {name: "South Korea", continent: "Asia"},
                  {name: "New Zealnd", continent: "Australia"}
              ]
        };
    }

    handleCloseModal = () => {
        this.setState({
            showModal: false
        });
    }

    showInfo = (name) => {
        this.setState({
            selectedCountry: this.state.countries.find(it => it.name===name),
            showModal: true
        });
    }

    render () {
        return (
            <div>
                {
                    this.state.countries.map((country) => <Country 
                        name={country.name} 
                        continent={country.continent} 
                        showInfo={this.showInfo}
                      />
                    )
                }
                <ReactModal 
                    isOpen={this.state.showModal}
                    contentLabel={this.state.selectedCountry.name}
                >
                    <div className="modal">
                        <div>{this.state.selectedCountry.name}</div>  
                        <div>{this.state.selectedCountry.continent}</div>  
                    </div>
                    <button onClick={this.handleCloseModal}>Close Modal</button>
                </ReactModal>
            </div>
        );
    }
}

const Country = (props) => {
    return (
        <div className="country" onClick={() => props.showInfo(props.name)}>
            <div>{props.name}</div>
            <span>-</span>
            <div>{props.continent}</div>  
        </div>
    )
};