Why is search form input data not being passed to its child component in React?

Viewed 19

In this weather app, I want the user to type a city into the "Body" component and have the weather results for the city display by updating the "Results" component.

I'm struggling to get the search query stored as {this.state.city} into the API call when exporting it from "Body" as prop cityProp={this.state.city}.

I'm able to access and log the inputted city name to the console. However, submitting it appears to have no effect on the location being displayed.

The goal is to display the temperature for the inputted city.

App:

import "./App.css";
import Header from "./Header";
import Body from "./Body";

function App() {
  return (
      <div>
        <Header />
        <Body />
      </div>
  );
}

export default App;

Body:

import React, { Component } from "react";
import "./App.css";
import Results from "./Results";
import { useState } from "react";

class Body extends Component {
  constructor(props) {
    super(props);
    this.state = { city: "London" };
  }
  handleCityChange = (e) => {
    this.setState({ city: e.target.value });
  };

  handleSubmit = (e) => {
    e.preventDefault();
    // this.setState({ city: e.target.value });
  };

  render() {
    return (
      <div >
        <form className="SearchForm" onSubmit={this.handleSubmit}>
          <label>
            <input
              value={this.state.city}
              onChange={this.handleCityChange}
            ></input>
            <button>Go</button>
          </label>
        </form>
        <Results cityProp={this.state.city} />
      </div>
    );
  }
}
export default Body;

Results:

import "./App.css";
import React from "react";
import { useState, useEffect } from "react";

const Results = (props) => {
  const [forecast, setForecast] = useState([]);
  const [location, setLocation] = useState([]);

  useEffect(() => {
    const getWeather = async () => {
      try {
        fetch(
          `http://api.weatherapi.com/v1/forecast.json?key=47b6acea5d204134b4661938220707&q="${props.cityProp}"&days=3&aqi=no`
        ).then((response) => {
          response.json().then((data) => {
            setForecast(data.forecast);
            setLocation(data.location);
          });
        });
      } catch (err) {
        console.log("Error");
      }
    };
    getWeather();
  }, []);

  const renderedContent = forecast.forecastday
    ? forecast.forecastday.map((item) => {
        return (
          <div key={item.date_epoch}>
            <div>{item.day.maxtemp_c}</div>
          </div>
        );
      })
    : null;

  return (

      <div>{renderedContent}</div>

  );
};

export default Results;
1 Answers

The effect in your Result component will not run when cityProp updates unless the prop is in the effect's dependency array:

  useEffect(() => {
    const getWeather = async () => {
      try {
        fetch(
          `http://api.weatherapi.com/v1/forecast.json?key=47b6acea5d204134b4661938220707&q="${props.cityProp}"&days=3&aqi=no`
        ).then((response) => {
          response.json().then((data) => {
            setForecast(data.forecast);
            setLocation(data.location);
          });
        });
      } catch (err) {
        console.log("Error");
      }
    };
    getWeather();
  }, [props.cityProp]);
Related