mfs
mfs

Reputation: 61

How to change SVG according to time

So I have this weather app I'm building in react that uses SVG icons which I want to change according to time. Right now this is the code that I have in my "WeatherIcon" component:

import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import sun from "./sun.svg";
import cloud from "./cloud.svg";
import moon from "./moon.svg";
import cloudnight from "./cloudnight.svg";

class WeatherIcon extends Component {
  humanizeDate = () => {
    // Had to multiply the timestamp by 1000 to make it compatible
    // Add timezone difference to the date
    // Substract 1 hour (3600 seconds) because of summer time
    // Talk to Maria if problem
    let date = new Date(
      this.props.timestamp * 1000 + (this.props.timezone - 3600) * 1000
    );
    let hours = date.getHours();
    return hours;
  };

  render() {
    if (this.props.description === "Clear") {
      return (
        <div className="sunny">
          <img src={sun} className="sun" alt="Sunny" />;
        </div>
      );
    }
    if (this.props.description === "Clouds") {
      return (
        <div className="cloudy">
          <img src={cloud} alt="Cloudy" />
        </div>
      );

    if (this.props.description === "Clear" && this.humanizeDate() > 19) {
      return (
        <div className="moon">
          <img src={moon} alt="Moon" />
        </div>
      );
    }
    if (this.props.description === "Clouds" && this.humanizeDate() > 19) {
      return (
        <div className="cloud-night">
          <img src={cloudnight} alt="Cloud-Night" />
        </div>
      );
    }
    if (this.props.description === "Clear" && this.humanizeDate() < 6) {
      return (
        <div className="moon">
          <img src={moon} alt="Moon" />
        </div>
      );
    }
    if (this.props.description === "Clouds" && this.humanizeDate() < 6) {
      return (
        <div className="cloud-night">
          <img src={cloudnight} alt="Cloud-Night" />
        </div>
      );
    }
  }
}

export default WeatherIcon;

this.props.description is the API description of the weather and the timestamp and timezone props are also API responses. Problem is it's 1 am right now and I'm still getting the sunny clouds instead the moon clouds. Any suggestions? (Don't tell me to talk to Maria as I am her 🤷‍♂️)

Upvotes: 1

Views: 273

Answers (1)

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15688

In the render() method, once you execute a return statement, all other logic below it will not run.

In your render(), you have a collection of if-checks, where as long as one of them passes, it will return its corresponding icon. The sunny-clouds icon check comes first AND it passes because its only checking if this.props.description == "Clear". You used return in that block, therefore, we get the sun-icon, and the rest of the if-checks do not run.

To workaround this, we can update your if-checks to be more inclusive of the hour boundaries for day and night. Based on the timeframes you've layed out, we only need four checks and they should look something like:

"Clear" and 6+ and <19 --> sun
"Clouds" and 6+ and <19 --> cloud
"Clear" and <6 or >=19 --> moon
"Clouds" and <6 or >=19 --> cloudnights

See working sandbox: https://codesandbox.io/s/hardcore-pascal-4nzes

Working code without Timezone difference:

import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import sun from "./sun.svg";
import cloud from "./cloud.svg";
import moon from "./moon.svg";
import cloudnight from "./cloudnight.svg";

class WeatherIcon extends Component {
  humanizeDate = () => {

    let date = new Date(this.props.timestamp);

    let hours = date.getHours();

    return hours;
  };

  renderIcon = () => {
    console.log(this.humanizeDate());
    if (
      this.props.description === "Clear" &&
      (this.humanizeDate() >= 6 && this.humanizeDate() < 19)
    ) {
      return (
        <div className="sunny">
          <img src={sun} className="sun" alt="Sunny" />;
        </div>
      );
    } else if (
      this.props.description === "Clouds" &&
      (this.humanizeDate() >= 6 && this.humanizeDate() < 19)
    ) {
      return (
        <div className="moon">
          <img src={cloud} alt="Moon" />
        </div>
      );
    } else if (
      this.props.description === "Clear" &&
      (this.humanizeDate() < 6 || this.humanizeDate() >= 19)
    ) {
      return (
        <div className="moon">
          <img src={moon} alt="Moon" />
        </div>
      );
    } else if (
      this.props.description === "Clouds" &&
      (this.humanizeDate() < 6 || this.humanizeDate() >= 19)
    ) {
      return (
        <div className="cloud-night">
          <img src={cloudnight} alt="Cloud-Night" />
        </div>
      );
    } else {
      return "woof";
    }
  };

  render() {
    return <div>{this.renderIcon()}</div>;
  }
}

export default WeatherIcon;

I didn't use the timezone logic because I wasn't entirely sure of what you want your timezone to be. With that said, this should paint the picture you want. :)

Upvotes: 1

Related Questions