2

I want to learn how to display the data from the API in reactjs..

This is the API and I want to display description property in the API whichis in weather[0] object and temp property which is in main object.

How to do it ?

This the code:

    import logo from './Images/logo.png';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Navbar, Button, Form, FormControl } from 'react-bootstrap';
import React, { Component } from "react";


class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};

  }

  componentDidMount() {
    if (navigator.geolocation) {
      navigator.geolocation.watchPosition(async function (position) {
        console.log("Latitude is :", position.coords.latitude);
        console.log("Longitude is :", position.coords.longitude);

        var lat = position.coords.latitude;
        var lon = position.coords.longitude;
    
        const url = `http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&units=metric&appid=ca148f5dc67f12aafaa56d1878bb6db2`;
        const response = await fetch(url);
        let data = await response.json();
        
        console.log(data);
      });
    }
  }

  render() {
    return (
      <div className="App">

        <Navbar bg="light" expand="lg">
          <Navbar.Brand href="#">Weather Forecast <img src={logo} alt="logo" width="50" height="50" /></Navbar.Brand>
          <Navbar.Toggle aria-controls="navbarScroll" />
          <Navbar.Collapse id="navbarScroll">

            <Form className="d-flex">
              <FormControl
                type="search"
                placeholder="Enter City"
                className="mr-2"
                aria-label="Search"
              />
              <Button variant="outline-success" className="searchBTN">Forecast</Button>
            </Form>
          </Navbar.Collapse>
        </Navbar>

      </div>
    );
  }
}

export default App;

Can I get some example how to display these properties on the page ?

SOLVED

Just replace async function (position) in navigator.geoposition function with async (position) => and the data come sucsessfully.

Blagovest Pizhev
  • 161
  • 3
  • 14
  • Write data into state and then in the render method call the state. – KiprasT Jul 27 '21 at 11:33
  • I want to display description property in the API whichis in weather[0] object and temp property which is in main object. Can I get some example how to to that ? – Blagovest Pizhev Jul 27 '21 at 11:34
  • Those are one of the most important React ideas, you should really try and read the documentation first before asking basic questions on stackoverflow: https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly – KiprasT Jul 27 '21 at 11:37

3 Answers3

2

You give another url for api but in your code, you're calling another url with some parameters. But if we assume the url is one that you mention in the question. You can call the api and take the result as the bellow:

import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { Navbar, Button, Form, FormControl } from "react-bootstrap";
import React, { Component } from "react";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  componentDidMount() {
    const url =
      "https://api.openweathermap.org/data/2.5/weather?q=plovdiv&units=metric&appid=ca148f5dc67f12aafaa56d1878bb6db2";
    fetch(url)
      .then((response) => response.json())
      .then((data) => this.setState(data))
      .catch((e) => {
        console.log(e);
      });
  }

  renderWeatherDescription = () => {
    if (this.state && this.state.weather && this.state.weather[0])
      return <p>{this.state.weather[0].description}</p>;
  };

  renderMainTemp = () => {
    if (this.state && this.state.main) return <p>{this.state.main.temp}</p>;
  };

  render() {
    return (
      <div className="App">
        <Navbar bg="light" expand="lg">
          <Navbar.Brand href="#">
            Weather Forecast <img alt="logo" width="50" height="50" />
          </Navbar.Brand>
          <Navbar.Toggle aria-controls="navbarScroll" />
          <Navbar.Collapse id="navbarScroll">
            <Form className="d-flex">
              <FormControl
                type="search"
                placeholder="Enter City"
                className="mr-2"
                aria-label="Search"
              />
              <Button variant="outline-success" className="searchBTN">
                Forecast
              </Button>
            </Form>
          </Navbar.Collapse>
        </Navbar>
        {this.renderWeatherDescription()}
        {this.renderMainTemp()}
      </div>
    );
  }
}

export default App;

Here's the executable sample:

Edit wonderful-frost-iehtc

Also you can check this link for complete answer with navigator:

Edit condescending-surf-luoue

Majid M.
  • 4,467
  • 1
  • 11
  • 29
  • API is the same like url, just API search by city the url search by coordinates – Blagovest Pizhev Jul 27 '21 at 12:28
  • @BlagovestPizhev It seems the code which you have written it to get `latitude` and `longitude` gives error. – Majid M. Jul 27 '21 at 12:53
  • @BlagovestPizhev Check the second code in the sandbox for the answer. But because of navigator given error, it calls again with first approach. – Majid M. Jul 27 '21 at 12:58
  • @BlagovestPizhev Why you changed the accepted answer? – Majid M. Jul 27 '21 at 16:33
  • Can you check here: https://stackoverflow.com/questions/68548672/how-to-set-parameters-from-gps-coordinates-in-api-url-and-get-data-in-one-functi – Blagovest Pizhev Jul 27 '21 at 16:36
  • Because this function componentDidMount not work fine with GPS coordinates.. I try with your way after try with codesandbox.. when API not have parameters in the url .. work fine... when put paramters in the url with geolocation function not worked for me... please help.. – Blagovest Pizhev Jul 27 '21 at 16:38
  • @BlagovestPizhev I will check it out and try to resolve the problem. – Majid M. Jul 27 '21 at 16:58
  • @BlagovestPizhev Are you sure that your api with parameter working successfully? – Majid M. Jul 27 '21 at 18:03
  • Yea, just copy url, replace q=plovdiv with lat=45&lon=25 or whatever you want coordinates.. – Blagovest Pizhev Jul 27 '21 at 18:22
  • @BlagovestPizhev It gives you error, because you should give access to your browser can access your location. If your using chrome, you can a location icon in the end of the address bar. Please click on it and give it access to your location. Please check out this link: https://stackoverflow.com/questions/20678707/ask-for-geolocation-permission-again-if-it-was-denied – Majid M. Jul 27 '21 at 18:24
  • If there is any error again, please leave a comment. – Majid M. Jul 27 '21 at 18:25
  • I will try after 15 minutes, but I think I use firefox and he ask me for the location, when I click allow I receive the error.. – Blagovest Pizhev Jul 27 '21 at 18:26
  • Also in the code, I've logged everything. You can find the problems. – Majid M. Jul 27 '21 at 18:26
  • There aren't any errors in the code I've written . The errors which you take is related to navigator api. – Majid M. Jul 27 '21 at 18:30
  • https://stackoverflow.com/questions/68550323/unhandled-rejection-typeerror-this-is-undefined-when-write-this-setstatedata – Blagovest Pizhev Jul 27 '21 at 18:50
  • @BlagovestPizhev Another person, answered your question. Have you achieved something you want? – Majid M. Jul 27 '21 at 19:02
  • Yes. I accept your answer just see the solution from my updated question.. – Blagovest Pizhev Jul 27 '21 at 19:04
1

In place, where you have console.log(data); just call this.setState({ ...something }).

You pass object to setState, so everything you pass is saved to state.

this.setState also triggers automatically rerender, so if you use in rendet method this.state, variables are updated and rerendered.

<div>{this.state.xxx}</div>

You can also render collection.

<div>{this.state.someArray.map((item) => item.description)}</div>
1

I do not know exactly how the API response looks like, you can console log it to see the exact structure of the response. This is an example of how to render it based on your description of the response object. The first thing you do is put the response object into the state, the second thing is you display it inside the render method (from the state).

import logo from './Images/logo.png';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Navbar, Button, Form, FormControl } from 'react-bootstrap';
import React, { Component } from "react";


class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};

  }

  componentDidMount() {
    if (navigator.geolocation) {
      navigator.geolocation.watchPosition(async (position) => {
        console.log("Latitude is :", position.coords.latitude);
        console.log("Longitude is :", position.coords.longitude);

        var lat = position.coords.latitude;
        var lon = position.coords.longitude;
    
        const url = `http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&units=metric&appid=ca148f5dc67f12aafaa56d1878bb6db2`;
        const response = await fetch(url);
        let data = await response.json();
        
        console.log(data);

        this.setState(data);
      });
    }
  }

  render() {
    return (
      <div className="App">

        <Navbar bg="light" expand="lg">
          <Navbar.Brand href="#">Weather Forecast <img src={logo} alt="logo" width="50" height="50" /></Navbar.Brand>
          <Navbar.Toggle aria-controls="navbarScroll" />
          <Navbar.Collapse id="navbarScroll">

            <Form className="d-flex">
              <FormControl
                type="search"
                placeholder="Enter City"
                className="mr-2"
                aria-label="Search"
              />
              <Button variant="outline-success" className="searchBTN">Forecast</Button>
            </Form>
          </Navbar.Collapse>
        </Navbar>

        <div>
            <p>{this.state.weather && this.state.weather[0].description}</p>
            <p>{this.state.main && this.state.main.temp}</p>
        </div>
      </div>
    );
  }
}

export default App;
afalak
  • 481
  • 5
  • 9
  • Cannot read property '0' of undefined I see this error when I use this code.. But in the constructor I not set data in setState only use this.setState(data); in the function ? Can you check the API above in my question.. http://api.openweathermap.org/data/2.5/weather?q=plovdiv&units=metric&appid=ca148f5dc67f12aafaa56d1878bb6db2 – Blagovest Pizhev Jul 27 '21 at 11:51
  • @BlagovestPizhev try doing this {this.state?.weather[0]?.description} – PCPbiscuit Jul 27 '21 at 13:06
  • I receive error: TypeError: _this$state.weather is undefined – Blagovest Pizhev Jul 27 '21 at 18:53
  • This error occurs because you are trying to display information from the state that does not yet exist on the first render. It needs a second to come from the API, then you can display it... I will update the answer to check if the information exists before displaying it. If you are using typescript you can use the "?" method that @PCPbiscuit mentioned. – afalak Jul 28 '21 at 08:02