Как изменить классы CSS в соответствии со временем, полученным API

Я создаю приложение погоды в React, и пока все хорошо. Проблема в том, что теперь я хочу иметь «светлый режим» и «темный режим», которые должны быть классами CSS, которые меняются в зависимости от времени восхода/захода солнца, полученного API. Когда я делал это в ванильном JS, я использовал функцию, которая преобразовывала метки времени в часы и сравнивала текущий час с восходом/закатом, а затем решала, какой класс представить, вот так

function getMode(response) {
  let today = response.data.dt;
  let timezone = response.data.timezone;
  let difference = today + timezone - 3600;
  let hours = timeConverter(difference);
  let mode = document.getElementById("app");
  let sunrise = response.data.sys.sunrise;
  let difference2 = sunrise + timezone - 3600;
  let currentSunrise = timeConverter(difference2);
  let sunset = response.data.sys.sunset;
  let difference3 = sunset + timezone - 3600;
  let currentSunset = timeConverter(difference3) - 1;
  if (hours > currentSunset) {
    mode.classList.add("darkmode").remove("lightmode");
  }
  else if (hours < currentSunrise) {
    mode.classList.add("darkmode").remove("lightmode");
  } else {
    mode.classList.remove("darkmode").add("lightmode");
  }
}

axios.get(apiUrl).then(getMode)
<body>
    <div id = "app" class = "lightmode">

Тогда CSS выглядел так

.lightmode h1 {
  font-family: "Josefin Sans", sans-serif;
  text-align: right;
  color: #06384d;
  font-size: 32px;
  font-weight: 700;
}

.lightmode {
  font-family: "Josefin Sans", sans-serif;
  background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
  border-style: solid;
  border-radius: 30px;
  border-color: #096386;
}

#app {
  margin: 10px 400px;
  padding: 10px 10px;
}

(...)

.darkmode h1 {
  font-family: "Josefin Sans", sans-serif;
  text-align: right;
  color: #fff;
  font-size: 32px;
  font-weight: 700;
}

.darkmode {
  font-family: "Josefin Sans", sans-serif;
  background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
  border-style: solid;
  border-radius: 30px;
  border-color: #096386;
}

И это работало нормально. Теперь в React (новичок здесь) я не знаю, как подойти к проблеме. Я читал о динамическом изменении классов CSS в React с состоянием, но не могу понять, как включить это в ответ API. Какие-либо предложения?

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
0
0
195
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ключевой частью динамически изменяющихся классов CSS в React будет:

<div className = {`App ${this.state.displayMode}`}>

Имя класса контейнера будет обновляться каждый раз, когда изменяется состояние displayMode и в этом примере добавляется к классу App, что приводит к App darkmode и отображается как таковое.

<div class = "App darkmode">

Пример кода/вариант использования:

class App extends Component {
  state = {
    displayMode: "lightmode"
  };

  getMode = response => {
    let _displayMode;
    // Logic for determining the mode
    return _displayMode;
  }

  componentDidMount() {
    // Make API call here and run your logic to determine the mode
    axios.get(apiUrl).then(getMode).then(displayMode => {
    // As a callback to your function, set the state for displayMode
      this.setState({
        displayMode: displayMode
      })
    });
  }

  render() {
    return (
      <div className = {`App ${this.state.displayMode}`}>
      </div>
    );
  }
}
Ответ принят как подходящий

Вы можете сохранить className в состоянии и изменить его в своей функции.

class Demo extends Component {
 constructor(props) {
    super(props);

    this.state = {
      stClass: "lightmode"

    }
 }
 state = {
    stClass: "lightmode"
 }

 componentDidMount = () => {
    [call your function here and change the state of stClass]  
  }

 render() {
    return (
      <div className = {`${this.state.stClass}`}>
       [your code here]
     </div>
    )
 }

}

Я использовал вариант вашего решения, чтобы лучше соответствовать моему коду (у меня уже есть componentDidMount, что означает, что я не могу вызывать его по аксиомам, он не будет знать, какой из них вызывать), и он работает нормально! Благодарю вас!

mfs 25.07.2019 07:06

Рад был помочь :)

Molly 25.07.2019 09:12

Другие вопросы по теме