Andrew Daly
Andrew Daly

Reputation: 537

Displaying Multiple API Responses in React

I am learning React and I have a solution that requests information through an API, and when there is a response it sets the state, however when rendering my results it only shows the last response on screen, enter image description here

Even though there are 4, see image below. enter image description here

App.js

import React from 'react';

import Tiles from './components/Tiles'
import Form from './components/Form'
import WaterData from './components/WaterData'

class App extends React.Component{

  state = {
    station_name: undefined,
    water_value: undefined,
    dateTime: undefined
  }

  getData = async (e) => {

    e.preventDefault();

    const name = e.target.elements.name.value;

    const api_call = await fetch(`https://waterlevel.ie/geojson/latest/`)
    .then(response1 => {
      response1.json().then(data =>{
        Array.from(data.features).forEach(element => {
          if(element.properties['station.name'] === name){
            this.setState({
              station_name: element.properties['station.name'],
              water_value: element.properties['value'],
              dateTime: element.properties['datetime'],
            });
          }
      })
    });
  });
}


   render(){
    return(
      <div>
        <Tiles />
        <Form loadData={this.getData}/>
        <WaterData 
           station_name={this.state.station_name}
           water_value={this.state.water_value}
           dateTime={this.state.dateTime}
        />
      </div>
   )
  }
}
export default App;

WaterData.js

import React from 'react';
const Weather = (props) => {


console.log(props)

  return(
    <li>
      <p>Location {props.station_name}</p>
      <p>Value {props.water_value}</p>
      <p>Date Time: {props.dateTime}</p>
    </li>
  )
}
export default Weather;

Can someone explain to me why the 4 responses do not display?

Upvotes: 3

Views: 1951

Answers (1)

Treycos
Treycos

Reputation: 7492

This happens because you are replacing the values in your state for each part of your data.

You can filter out the element you want in your array using filter.

And then put the whole array into your state only once :

const api_call = await fetch(`https://waterlevel.ie/geojson/latest/`)
.then(response1 => {
  response1.json().then(data => {
    const features = Array.from(data.features)
      .filter(el => el.properties['station.name'] === name);
    this.setState({ features });
  })
});

But now, to render all of them, you will need to map your state values :

   render(){
    return(
      <div>
        <Tiles />
        <Form loadData={this.getData}/>
        {this.state.features.map(feat => <WaterData 
           key={/* Find something unique*/}
           station_name={feat.properties['station.name']}
           water_value={feat.properties['value']}
           dateTime={feat.properties['datetime']}
        />)}
      </div>
    )
  }

There's no need to store all the value separately in your state if they are related to each other, it would be fine for your child component though.

To be sure that the state value is always an array, give it an empty array at the start of your class :

  state = {
    features: []
  }

Upvotes: 3

Related Questions