Como criar um aplicativo de controle de temperatura no React – Dicas e código inicial

O que estamos construindo

Neste projeto React para iniciantes, vamos aprender como usar ganchos de estado, manipular eventos, aplicar CSS com base no estado e muito mais! Confira:

Prefere tutoriais em vídeo?

Confira o tutorial do YouTube aqui.

Tente você mesmo

Se você quiser experimentar primeiro, aqui estão os cenários (você também pode pegar o código CSS / iniciador abaixo):

  • Quando o usuário clica no “botão aumentar”, a temperatura deve aumentar
  • A temperatura não pode ultrapassar 30
  • Quando o usuário clica no “botão diminuir”, a temperatura deve diminuir
  • A temperatura não pode ficar abaixo de 0
  • Quando a temperatura é 15 ou superior, a cor do plano de fundo deve mudar para vermelho (DICA: incluí um estilo chamado “quente” que você pode usar)
  • Quando a temperatura estiver abaixo de 15, a cor do plano de fundo deve ser azul (DICA: incluí um estilo chamado “frio” que você pode usar)

Código de instalação / arranque

NOTA: Suponho que você tenha uma configuração do ambiente de desenvolvimento React. Se não, confira este vídeo para ajudar você a começar.

Tudo o que precisamos para começar é usar create-react-app. Ligue um terminal e execute:

npx create-react-app temperature-control

Deixe o terminal fazer seu trabalho e abra o projeto no VS Code (ou o que você usar).

Em seguida, vá para index.js, exclua tudo e cole o seguinte:

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')
);

Entrar index.css, exclua tudo e cole o seguinte:

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;
}

Por fim, entre App.js, exclua tudo e cole o seguinte:

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;

Agora podemos abrir um terminal no VS Code e executar o seguinte:

npm start

Se tudo correu como planejado, você deve ver o seguinte:

Viva! Isso nos dá um bom modelo para brincar, sem ter que se preocupar com nenhum CSS.

Torne o valor da temperatura dinâmico – usando State

A primeira coisa que faremos é tornar o valor da temperatura dinâmico. Para fazer isso, vamos armazenar o valor da temperatura no estado. Isso facilita a obtenção do valor posteriormente e a execução da lógica usando-o.

Se algo mudar na sua interface do usuário, é uma boa ideia colocá-la em estado.

No App.js importar o useState prenda na parte superior do arquivo da seguinte maneira:

import React, { useState } from 'react';

Em seguida, adicione o seguinte dentro do Função de aplicativo:

const [temperatureValue, setTemperatureValue] = useState(10);

Uma rápida atualização sobre useState – permite manter dados no estado do componente. o useState hook nos dá duas coisas:

  • uma variável que contém o valor do estado atual
  • uma função para alterar o valor do estado.

Nesse caso, chamamos nossa variável de estado temperatureValue e chamou nossa função setTemperatureValue. Inicializamos nosso valor da temperatura para ter um valor de 10, passando o valor 10 ao gancho useState.

Agora que temos um valor de estado, é hora de usá-lo em nosso código. Lembre-se, as coisas que obtemos useState pode usar usado como qualquer variável e função JavaScript antiga (já que é isso que elas são).

Dentro do nosso JSX, queremos substituir o valor da temperatura codificado usando nossa nova variável de estado sofisticada. Mude esta linha:

<div className="temperature-display">10°C</div>

Para que se torne o seguinte:

<div className="temperature-display">{temperatureValue}°C</div>

Observe como usamos {} para renderizar nossa temperatureValue variável. Agora, quando nosso valor de temperatura for alterado, o componente será renderizado novamente e exibirá o novo valor de temperatura.

Nosso App.js arquivo até agora se parece com este:

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;

Agora, se você executar o aplicativo e olhar para o navegador, verá que as coisas têm a mesma aparência de antes.

Mas se você mudar o valor inicial que passamos para o gancho useState de 10 para outra coisa (por exemplo, 15), você verá que o aplicativo é atualizado. Isso significa que nosso gancho de estado está funcionando!

Alterar estado ao clicar no botão

Vamos trabalhar para aumentar / diminuir o valor da temperatura quando os botões são clicados.

Como sabemos, o gancho useState nos fornece uma setTemperatureValue função que podemos usar para mudar o temperaturaValor. Então, faz sentido ligarmos isso ao botão onClick evento.

Vamos fazer o botão de aumento primeiro. Substitua o botão de aumento pelo seguinte:

<button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>

Observe como isso chama o setTemperatureValue função. Tomamos a corrente temperatureValue, adicione 1 e passe isso como argumento.

Portanto, como o TemperatureValue começa em 10, adicionar 1 definirá o valor do estado como 11. Quando o botão for clicado novamente, o estado será definido como 12 e assim por diante.

Em seguida, faremos o mesmo com o botão diminuir. Substitua o botão de diminuição atual pelo seguinte:

<button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>

Isso está fazendo a mesma coisa, exceto que estamos diminuindo a temperatureValue desta vez.

Nosso código agora se parece com isso:

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;

Tente executar isso no navegador e clicar nos botões. Os valores vão aumentar / diminuir.

Alterando a cor com base no estado

Agora vamos fazer algumas coisas chiques. Queremos que a cor de fundo da tela mude, dependendo da temperatura (alta ou baixa).

Se a temperatura é de 15 graus ou mais, queremos mudar a cor de fundo para vermelho. Se tiver menos de 15 anos, queremos alterar a cor do plano de fundo para azul.

Se você der uma olhada no CSS, forneci 2 classes:

  • .cold que define o plano de fundo para azul
  • .hot que define o fundo para vermelho

Se adicionarmos uma dessas classes ao display de temperatura div, muda de cor. Por exemplo:

<div className="temperature-display cold">{temperatureValue}°C</div>

dará à tela de temperatura um fundo azul, enquanto:

<div className="temperature-display hot">{temperatureValue}°C</div>

dará à tela de temperatura um fundo vermelho.

Ok, isso é legal e tudo, mas como é que dinamicamente adicionar essas classes com base no estado?

Lembre-se de que geralmente é uma boa ideia colocar no estado as coisas que podem mudar na sua interface do usuário. Portanto, state é um lugar perfeito para armazenar a classe CSS atual que queremos usar.

Vamos em frente e criar outro gancho de estado para segurar o temperaturaCor igual a:

const [temperatureColor, setTemperatureColor] = useState('cold');

Observe que inicializamos nossa temperaturaCor objeto de estado com um valor “frio” (como nosso valor de temperatura é inicialmente 10 graus, queremos que a cor do plano de fundo seja azul).

Podemos então usar literais de modelo para adicionar dinamicamente as classes que queremos usando essa variável de estado. Vá em frente e atualize o código com o seguinte:

<div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>

Essa é uma sintaxe complicada de entender; portanto, não se preocupe se não entender imediatamente.

Tudo o que está fazendo é criar uma string e aplicar dinamicamente o temperaturaCor variável. Sempre que o temperaturaCor muda para “hot”, o componente será renderizado novamente e a classe CSS “hot” será adicionada à string className.

Nosso código até agora se parece com este:

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;

Mude a inicial temperatureColor variável de estado para “quente” / “frio” e o fundo da tela de temperatura deve mudar.

Agora que sabemos que isso está funcionando, tudo o que precisamos fazer é alterar a variável de estado. Mas onde fazemos isso?

Bem, nós já temos um Manipulador onClick que altera o temperatureValue, faz sentido adicionar nossa nova lógica a esse manipulador.

Até agora, temos usado um função embutida para nossos manipuladores de eventos de clique. E usar funções embutidas é bom quando temos uma função de uma linha.

Mas quando temos uma função de várias linhas com um monte de lógica, é melhor mover a função para fora do JSX. Isso torna nosso código um pouco mais limpo.

Vá em frente e cole o seguinte logo abaixo de todas as coisas do estado:

const increaseTemperature = () => {
	setTemperatureValue(temperatureValue + 1);
};

const decreaseTemperature = () => {
	setTemperatureValue(temperatureValue - 1);
};

Aqui estamos definindo duas funções – uma que aumenta a temperatura e outra que diminui a temperatura.

Em seguida, queremos alterar os botões onClick propriedades para chamar essas funções em vez das funções embutidas que tínhamos anteriormente:

    <button onClick={increaseTemperature}>+</button>
    <button onClick={decreaseTemperature}>-</button>

Agora, em vez de usar uma função embutida, estamos passando uma referência para nosso raiseTemperature e decrementTemperature funções. Nosso código até agora se parece com este:

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;

Observe como nada mudou ainda – estamos apenas refatorando nosso código e se preparando para as próximas mudanças.

Agora é muito mais fácil adicionar lógica de código para qualquer um dos eventos de clique no botão – apenas escrevemos nossa lógica na função apropriada e a vida é boa.

ESTÁ BEM! Com a refatoração de diversão fora do caminho, vamos voltar aos negócios. Então nós dissemos que Quando a temperatura é de 15 graus ou mais, queremos alterar o valor do estado temperatureColor.

Podemos adicionar essa lógica ao nosso raiseTemperature funcionar assim:

const increaseTemperature = () => {
	const newTemperature = temperatureValue + 1;
	setTemperatureValue(newTemperature);

	if (newTemperature >= 15) {
		setTemperatureColor('hot');
	}
};

O que nos fizemos?

  • Criamos uma variável para armazenar o newTemperature value (fizemos isso, pois usaremos essa variável em alguns lugares)
  • Nós definimos o temperatureValue, como fizemos antes
  • Nós escrevemos um declaração if para verificar se o newTemperature valor é maior ou igual a 15
  • Se sim, então usamos o setTemperatureColor para definir como temperaturaCor valor do estado como “quente”

Portanto, sempre que clicamos no botão várias vezes, o temperatureValue for maior ou igual a 15, o valor temperaturaCor mudanças de variável, o componente é renderizado novamente e a classe “quente” é adicionada à exibição de temperatura como bruxaria.

Mas espere! Ainda não lidamos com a redução. O que é basicamente semelhante à função de aumento:

const decreaseTemperature = () => {
	const newTemperature = temperatureValue - 1;
	setTemperatureValue(newTemperature);
	if (newTemperature < 15) {
		setTemperatureColor('cold');
	}
};

Desta vez, subtraímos um e verificamos se o novo valor está abaixo de 15 antes de alterar o temperatura cor

Nosso código final do aplicativo se parece com este:

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;

Execute o aplicativo e tudo deve funcionar – viva!

Um desafio para tentar

Você deve ter notado que nosso controle de temperatura não é muito seguro – o usuário pode aumentar a temperatura até atingir 100 ° C, fervendo até o esquecimento, ou diminuir a temperatura até atingir -100 ° C, transformando-se em um enorme gelo cubo.

O desafio, se você aceitar, é impedir que o valor da temperatura indo acima de 30 ° C, e impedi-lo de indo abaixo de 30 ° C.

DICA: O raiseTemperature e decrementTemperature funções são lugares perfeitos para adicionar essa lógica!