Thought Process Behind Making a React App - Weather App

Thought Process Behind Making a React App - Weather App

Source Code

Live Preview

Today, We are going to look into the Mindset required to create a Complex but Simple Looking Weather App.

Since the Data is availaible via API called WeatherAPI, we are going to use that to request weather data when specific city is typed.

As usual I will not dicuss anything about CSS (except when neccessary) as design is something that has nothing to do with the programming of app. The sky's the limit and you can do any design you want.

After creating a React App with npx create-react-app {app-name}, we have to think that there are two API's that we will use.

One gives us recommendations when we half-typed a city's name and other displays the weather data of that city when selected.

Let's create a Rough Structure in our Mind

First we create a input where on each change, the changed input is used to fetch reccomendations and displayed. Second, when the reccommended data (CityName) is clicked, the CityName is passed in function which fetches the weather data of that city and displays it.

Now Let's Code this,

We create a Search Bar Component in which a Input Element would be present which will call the API again and again when there is a change in the Input, as this will provide the reccommendations of name a/q to the name of the city typed in input.

So in Search Bar Component in App.js,

const SearchBar = () => {
  // we use useContext for better management of states
  const { 
    searchTerm, 
    setSearchTerm, 
    recommendation 
  } = useGlobalContext();
  // 1. setSearchTerm will be used to set the term we type in 
  //    input element
  // 2. that input value is then displayed in the input element via 
  //    searchTerm,
  // 3. the recommendation which will be displayed here is the data 
  //    i.e is received after request with value of searchTerm is made
  // 4. Request is done in context.js page where the api is :  
  //    https://api.weatherapi.com/v1/search.json?
  //    key={Your_Key_Provided_When_You_Create_an_Account}&
  //    q=${searchTerm} 
  return (
    <div className="searchBar">
      <p className="info">
        {/* neccessary instructions */}
        Search and Select the City, Only then the Weather Data of the 
        City will be Displayed :
      </p>
      <input
        type="text"
        name="search"
        // the setSearchTerm is called everytime when there is 
        // change in input
        // making the process of calling the reccommendations via API 
        // again and again, thus displaying reccommended data a/q
        onChange={(e) => setSearchTerm(e.target.value)}
        value={searchTerm}
      />
      {recommendation.length > 0 && <Recommendations />}
    </div>
  );
};

Now let's see how the data is requested in context.js

  useEffect(() => {
    // this runs with each change in searchTerm state
    fetchData();
  }, [searchTerm]);

  const fetchData = async () => {
    // now when this runs the data is fetched a/q to the 
    // input in searchTerm
    try {
      const res = await fetch(
        `https://api.weatherapi.com/v1/search.json? 
          key=5baa84cbff214636ad162010223006&q=${searchTerm}`
      );
      const data = await res.json();
      if (data.length > 0) {
        const cityNameRecommendations = data.map((place) => {
          return {
            name: place.name,
            region: place.region,
            country: place.country,
          };
        });
        // data added if present
        setRecommendation([...cityNameRecommendations]);
      } else {
        // if not, empty array is placed to not display anything
        setRecommendation([]);
      }
    } catch (error) {
      console.log(error);
    }
  };

The data is then rendered a/q below the input element in Recommendations Component

const Recommendations = () => {
  const {
    setRecommendation,
    recommendation,
    fetchCurrentWeather,
    setSearchTerm,
  } = useGlobalContext();

  // this runs after one of the displayed data
  // is clicked, this clears the reccomendations,
  // clears the input element,
  // and sends the cityName clicked to fetch the
  // weather data
  const handleClick = (rec) => {
    setRecommendation([]);
    fetchCurrentWeather(rec);
    setSearchTerm("");
  };

  return (
    <div className="recommendations">
      {/* the data is displayed */}
      {recommendation.map((rec, id) => (
        <div
          key={id}
          // when clicked on it, a function is triggered
          // the name is also passed
          onClick={() => handleClick(rec.name)}
          className="recommendation"
        >
          {rec.name}, {rec.region}, {rec.country}
        </div>
      ))}
    </div>
  );
};

Furthermore, we see how the sent cityName data is used to fetch Weather Data

  const fetchCurrentWeather = async (cityName) => {
    try {
      const res = await fetch(
        `https://api.weatherapi.com/v1/current.json?
         key=5baa84cbff214636ad162010223006&
         q=${cityName}&aqi=yes`
      );
      const data = await res.json();
      // the received data is set in currentWeather State
      setCurrentWeather([data]);
    } catch (error) {
      console.log(error);
    }
  };

Finally, in the DisplayInfo Component, the data is rendered.

We also add a feature where the AQI Data Background Color is changed a/q to it's data.

const DisplayInfo = () => {
  // we use useRef to access the properties of element
  // in which the background color is to be set
  const aqi = useRef();

  // weather data received is destructured
  const { currentWeather } = useGlobalContext();
  const [data] = currentWeather;
  const { current } = data;

  // we use it as short form
  const pm10 = current.air_quality.pm10;

  // this renders when the weather-data is loaded
  useEffect(() => {
    // we use it as short form as well
    const style = aqi.current.style;
    // a/q to the pm10 data, the colors are added
    // to give it graphical meaning
    if (pm10 <= 50) {
      style.backgroundColor = "#d4e6a5";
      style.color = "black";
    } else if (pm10 > 50 && pm10 <= 100) {
      style.backgroundColor = "#e5e6a5";
      style.color = "black";
    } else if (pm10 > 100 && pm10 <= 150) {
      style.backgroundColor = "#e6d5a5";
      style.color = "black";
    } else {
      style.backgroundColor = "#e6a9a5";
      style.color = "black";
    }
  });

  return (
    <div className="weather">
      <div className="current-condition">
        <div className="img">
          <img src={current.condition.icon} alt="weather-icon" />
        </div>
        <div className="weather-data">
          <p>
            <span>Location:</span>
            {data.location.name}
          </p>
          <p>
            <span>Weather:</span>
            {current.condition.text}
          </p>
          <p>
            <span>Last Updated:</span>
            {current.last_updated}
          </p>
          <p>
            <span>Temp (&deg;C):</span>
            {current.temp_c}
          </p>
        </div>
      </div>
      {/* the aqi useRef is used here to access it's properties */}
      <div className="aqi" ref={aqi}>
        <p>
          <span className="aqi-data">
            AirQuality (PM<sup>10</sup>):
          </span>
          {Math.floor(pm10)}
        </p>
      </div>
    </div>
  );
}

Hence, with this we finally create the project after adding designs and we are ready to deploy it to display it on internet.

I hope you understood the thought process that got involved in it. I wrote it as if I was trying to imagine myself on how to create this app in first place.

I hope you enjoyed it, till then Keep Making Apps

P. S - Constructive Criticism Always Welcomed ✌