Как создать приложение для контроля температуры в React - (в комплекте советы и стартовый код)
В этом проекте React для начинающих мы узнаем, как использовать хуки состояния, обрабатывать события, применять CSS на основе состояния и многое другое!
Предпочитаете видеоуроки?
Ознакомьтесь с руководством по YouTube здесь.
Попробуй сам
Если вы хотите сначала попробовать, вот сценарии (вы также можете взять код CSS / начальный код ниже):
- Когда пользователь нажимает кнопку «увеличить», температура должна увеличиваться.
- Температура не может быть выше 30
- Когда пользователь нажимает кнопку «уменьшить», температура должна снизиться.
- Температура не может опускаться ниже 0
- При температуре 15 или выше цвет фона должен измениться на красный (СОВЕТ: я включил стиль под названием «hot», который вы можете использовать).
- Когда температура ниже 15, цвет фона должен быть синим (ПОДСКАЗКА: я включил стиль под названием «cold», который вы можете использовать).
Настройка / стартовый код
ПРИМЕЧАНИЕ. Я предполагаю, что у вас настроена среда разработки React. Если нет, посмотрите это видео, которое поможет вам начать работу.
Все, что нам нужно для начала, - это использовать приложение create-response-app. Запустите терминал и начинаем:
npx create-react-app temperature-control
Пусть терминал делает свое дело и открывает проект в VS-коде (или чем бы вы ни пользовались).
Затем перейдите в index.js, удалите все и вставьте следующее:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Зайдите в index.css, удалите все и вставьте следующее:
body {
font-family: sans-serif;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
}
.app-container {
height: 400px;
width: 300px;
background: #2b5870;
border-radius: 20px;
box-shadow: 10px 10px 38px 0px rgba(0, 0, 0, 0.75);
}
.temperature-display-container {
display: flex;
justify-content: center;
align-items: center;
height: 70%;
}
.temperature-display {
display: flex;
border-radius: 50%;
color: #ffffff;
height: 220px;
width: 220px;
text-align: center;
justify-content: center;
align-items: center;
font-size: 48px;
border: 3px #ffffff solid;
transition: background 0.5s;
}
button {
border-radius: 100px;
height: 80px;
width: 80px;
font-size: 32px;
color: #ffffff;
background: rgb(105, 104, 104);
border: 2px #ffffff solid;
}
button:hover {
background: rgb(184, 184, 184);
cursor: pointer;
}
button:focus {
outline: 0;
}
.button-container {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.neutral {
background: rgb(184, 184, 184);
}
.cold {
background: #035aa6;
}
.hot {
background: #ff5200;
}
Наконец, зайдите в App.js, удалите все и вставьте следующее:
import React from 'react';
const App = () => {
return (
<div className='app-container'>
<div className='temperature-display-container'>
<div className='temperature-display'>10°C</div>
</div>
<div className='button-container'>
<button>+</button>
<button>-</button>
</div>
</div>
);
};
export default App;
Теперь мы можем открыть терминал в VS Code и запустить следующее
npm start
Если все прошло по плану, вы должны увидеть следующее:
Ура! Это дает нам хороший шаблон, с которым можно поиграть, не беспокоясь о CSS.
Сделайте значение температуры динамическим - с помощью State
Первое, что мы сделаем, это сделаем значение температуры динамическим. Для этого мы сохраним значение температуры в состоянии. Это облегчает нам получение значения позже и выполнение логики с его использованием.
Если что-то изменится в вашем пользовательском интерфейсе, рекомендуется сохранить это состояние.
В App.js импортируйте хук useState вверху файла, например:
import React, { useState } from 'react';
Затем добавьте в функцию приложения следующее:
const [temperatureValue, setTemperatureValue] = useState(10);
Напоминаем об useState - он позволяет нам сохранять данные в состоянии компонента. Хук UseState дает нам 2 вещи:
- переменную, которая содержит значение текущего состояния
- функцию для изменения значения состояния
В этом случае мы назвали нашу переменную состояния temperatureValue и назвали нашу функцию setTemperatureValue. Мы инициализировали нашу temperatureValue, чтобы она имела значение 10, передав значение 10 в хук useState.
Теперь, когда у нас есть значение состояния, пришло время использовать его в нашем коде. Помните, то, что мы получаем от useState, может использоваться точно так же, как любая старая переменная JavaScript и функция.
В нашем JSX мы хотим заменить жестко запрограммированное значение температуры, используя нашу новую причудливую переменную состояния. Измените эту строку:
<div className='temperature-display'>10°C</div>
Чтобы получилось так:
<div className='temperature-display'>{temperatureValue}°C</div>
Обратите внимание, как мы использовали {} для рендеринга нашей переменной temperatureValue. Теперь, когда наше значение температуры изменится, компонент повторно отрендерит и отобразит новое значение температуры.
Наш файл App.js пока выглядит так:
import React, { useState } from 'react';
const App = () => {
const [temperatureValue, setTemperatureValue] = useState(10);
return (
<div className='app-container'>
<div className='temperature-display-container'>
<div className='temperature-display'>{temperatureValue}°C</div>
</div>
<div className='button-container'>
<button>+</button>
<button>-</button>
</div>
</div>
);
};
export default App;
Теперь, если вы запустите приложение и посмотрите в браузер, вы увидите, что все выглядит так же, как и раньше.
Но если вы измените начальное значение, которое мы передаем хуку useState, с 10 на другое (например, 15), вы увидите, что приложение обновляется. Это означает, что наш хук состояния работает!
Изменение состояния при нажатии кнопки
Давайте поработаем над тем, чтобы значение температуры увеличивалось / уменьшалось при нажатии кнопок.
Как мы знаем, хук useState дает нам функцию setTemperatureValue, которую мы можем использовать для изменения temperatureValue. Итак, для нас имеет смысл связать это с событием кнопки onClick.
Сначала сделаем кнопку увеличения. Замените кнопку увеличения на следующую:
<button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>
Обратите внимание, как это вызывает функцию setTemperatureValue. Мы берем текущее значение temperatureValue, добавляем к нему 1 и передаем его в качестве аргумента.
Итак, поскольку значение temperatureValue начинается с 10, добавление 1 установит значение состояния равным 11. При повторном нажатии кнопки состояние устанавливается на 12 и так далее.
Далее сделаем то же самое с кнопкой уменьшения. Замените текущую кнопку уменьшения на следующую:
<button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>
Это делает то же самое, за исключением того, что на этот раз мы уменьшаем значение temperatureValue.
Теперь наш код выглядит так:
import React, { useState } from 'react';
const App = () => {
const [temperatureValue, setTemperatureValue] = useState(10);
return (
<div className='app-container'>
<div className='temperature-display-container'>
<div className='temperature-display'>{temperatureValue}°C</div>
</div>
<div className='button-container'>
<button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>
<button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>
</div>
</div>
);
};
export default App;
Попробуйте запустить это в браузере и нажимать кнопки. Значения будут увеличиваться / уменьшаться.
Изменение цвета в зависимости от состояния
А теперь займемся кое-чем необычным. Мы хотим, чтобы цвет фона дисплея менялся в зависимости от того, насколько высока (или низка) температура.
Если температура 15 градусов и выше, мы хотим изменить цвет фона на красный. Если он меньше 15, мы хотим изменить цвет фона на синий.
Если вы посмотрите на CSS, я предоставил 2 класса:
.cold
который устанавливает синий фон.hot
который устанавливает красный фон
Если мы добавим любой из этих классов в div отображения температуры, он изменит цвет. Например:
<div className='temperature-display cold'>{temperatureValue}°C</div>
придаст дисплею температуры синий фон, а:
<div className='temperature-display hot'>{temperatureValue}°C</div>
придает отображению температуры красный фон.
Это хорошо и все такое, но как нам динамически добавлять эти классы в зависимости от состояния?
Помните, как правило, неплохо привести в состояние то, что может измениться в вашем пользовательском интерфейсе. Таким образом, состояние - идеальное место для хранения текущего класса CSS, который мы хотим использовать.
Давайте продолжим и создадим еще один обработчик состояния для хранения temperatureColor следующим образом:
const [temperatureColor, setTemperatureColor] = useState('cold');
Обратите внимание, что мы инициализируем наш объект состояния temperatureColor со значением «cold» (поскольку наше значение температуры изначально равно 10 градусам, мы хотим, чтобы цвет фона был синим).
Затем мы можем использовать шаблонные литералы для динамического добавления нужных нам классов с помощью этой переменной состояния. Продолжайте и обновите код следующим образом:
<div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
Это сложный для понимания синтаксис, поэтому не волнуйтесь, если вы сразу не поймете.
Все, что это делает, - это создание строки и динамическое применение переменной temperatureColor. Всякий раз, когда temperatureColor изменяется на «hot», компонент будет повторно визуализироваться, и вместо этого в строку className будет добавлен класс CSS «hot».
Наш код пока выглядит так:
import React, { useState } from 'react';
const App = () => {
const [temperatureValue, setTemperatureValue] = useState(10);
const [temperatureColor, setTemperatureColor] = useState('cold');
return (
<div className='app-container'>
<div className='temperature-display-container'>
<div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
</div>
<div className='button-container'>
<button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>
<button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>
</div>
</div>
);
};
export default App;
Измените начальную переменную состояния temperatureColor на «hot» / «cold», и фон отображения температуры должен измениться.
Теперь, когда мы знаем, что это работает, все, что нам нужно сделать, изменить переменную состояния. Но где нам это делать?
Что ж, у нас уже есть обработчик onClick, который изменяет значение temperatureValue, поэтому имеет смысл добавить в этот обработчик нашу новую логику.
До сих пор мы использовали встроенную функцию для наших обработчиков событий. А использование встроенных функций хорошо, когда у нас есть однострочная функция.
Но когда у нас есть многострочная функция с кучей логики, лучше вынести функцию за пределы JSX. Это делает наш код немного чище.
Идите вперед и вставьте следующее чуть ниже всего состояния:
const increaseTemperature = () => {
setTemperatureValue(temperatureValue + 1);
};
const decreaseTemperature = () => {
setTemperatureValue(temperatureValue - 1);
};
Здесь мы определяем две функции - одну, которая увеличивает температуру, а другая - понижает температуру.
Затем мы хотим изменить свойства onClick нашей кнопки для вызова этих функций вместо встроенных функций, которые у нас были ранее:
<button onClick={increaseTemperature}>+</button>
<button onClick={decreaseTemperature}>-</button>
Теперь вместо использования встроенной функции мы передаем ссылку на наши функции увеличения температуры и уменьшения температуры. Наш код пока выглядит так:
import React, { useState } from 'react';
const App = () => {
const [temperatureValue, setTemperatureValue] = useState(10);
const [temperatureColor, setTemperatureColor] = useState('cold');
const increaseTemperature = () => {
setTemperatureValue(temperatureValue + 1);
};
const decreaseTemperature = () => {
setTemperatureValue(temperatureValue - 1);
};
return (
<div className='app-container'>
<div className='temperature-display-container'>
<div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
</div>
<div className='button-container'>
<button onClick={increaseTemperature}>+</button>
<button onClick={decreaseTemperature}>-</button>
</div>
</div>
);
};
export default App;
Обратите внимание, что пока ничего не изменилось - мы просто рефакторируем наш код и готовимся к предстоящим изменениям.
Теперь намного проще добавить логику кода для любого из событий нажатия кнопки - мы просто пишем нашу логику в соответствующей функции, и жизнь налаживается.
ХОРОШО! Избавившись от рефакторинга, давайте вернемся к делу. Итак, мы сказали, что когда температура составляет 15 градусов или больше, мы хотим изменить значение состояния temperatureColor.
Мы можем добавить эту логику к нашей функции увеличения температуры следующим образом:
const increaseTemperature = () => {
const newTemperature = temperatureValue + 1;
setTemperatureValue(newTemperature);
if (newTemperature >= 15) {
setTemperatureColor('hot');
}
};
Что мы сделали?
- Мы создали переменную для хранения значения newTemperature (мы сделали это, поскольку будем использовать эту переменную в нескольких местах)
- Мы устанавливаем значение temperatureValue, как и раньше.
- Мы написали оператор if, чтобы проверить, не превышает ли значение newTemperature 15
- Если да, то мы используем функцию setTemperatureColor, чтобы установить значение состояния temperatureColor как "hot".
Поэтому всякий раз, когда мы нажимаем кнопку достаточно раз, чтобы значение temperatureValue было больше или равно выше 15, переменная temperatureColor изменяется, компонент перерисовывается, и класс «hot» добавляется к отображению температуры, как в колдовстве.
Но подождите! Мы еще не справились с уменьшением. Что в принципе аналогично функции увеличения:
const decreaseTemperature = () => {
const newTemperature = temperatureValue - 1;
setTemperatureValue(newTemperature);
if (newTemperature < 15) {
setTemperatureColor('cold');
}
};
На этот раз мы вычитаем единицу и проверяем, меньше ли новое значение 15, прежде чем менять цвет температуры.
Наш окончательный код приложения выглядит так:
import React, { useState } from 'react';
const App = () => {
const [temperatureValue, setTemperatureValue] = useState(10);
const [temperatureColor, setTemperatureColor] = useState('cold');
const increaseTemperature = () => {
const newTemperature = temperatureValue + 1;
setTemperatureValue(newTemperature);
if (newTemperature >= 15) {
setTemperatureColor('hot');
}
};
const decreaseTemperature = () => {
const newTemperature = temperatureValue - 1;
setTemperatureValue(newTemperature);
if (newTemperature < 15) {
setTemperatureColor('cold');
}
};
return (
<div className='app-container'>
<div className='temperature-display-container'>
<div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
</div>
<div className='button-container'>
<button onClick={increaseTemperature}>+</button>
<button onClick={decreaseTemperature}>-</button>
</div>
</div>
);
};
export default App;
Запустите приложение и все должно заработать - ура!
Задача попробовать
Возможно, вы заметили, что наш контроль температуры не очень безопасен - пользователь может повышать температуру до 100 ° C, доводя себя до небытия, или понижать температуру до -100 ° C, превращаясь в массивный лед. куб.
Задача, если вы решите принять ее, состоит в том, чтобы предотвратить превышение значения температуры над 30°C и предотвратить его понижение до 30°C.
СОВЕТ: Функции увеличения и уменьшения температуры - идеальное место для добавления этой логики!