I built a celsius(as input) to fahrenheit(as output) conveter with react But
I want to switch between celsius and fahrenheit as input and output
I mean when I click on fahrenheit it turn to input and use can edit it an type init and see
celsius as result(as output) and viceversa
What to do to switch between input and output?
import { useState } = React;
function App() {
// Use State
const [celsius_value, set_celsius_value] = useState("");
const [fahrenheit_value, set_fahrenheit_value] = useState("");
// state functions
const celsius_to_fahrenheit_converter = (e) => {
const celsius_value_input = Number(e.target.value);
set_celsius_value(celsius_value_input);
// convert value
set_fahrenheit_value((celsius_value_input * 9) / 5 32);
};
const fahrenheit_to_celsius_converter = (e) => {
const fahrenheit_value_input = Number(e.target.value);
set_fahrenheit_value(fahrenheit_value_input);
// Convet value
set_celsius_value(((fahrenheit_value_input - 32) * 5) / 9);
};
return (
<div className="container">
{/* Celsius */}
<div className="celsius-container">
<label htmlFor="celsius-input">celsius</label>
<input
type="number"
name="celsius"
id="celsius-input"
value={celsius_value}
onChange={(e) => {
celsius_to_fahrenheit_converter(e);
}}
/>
</div>
{/* fahrenheit */}
<div className="fahrenheit -container">
<label htmlFor="fahrenheit -input">fahrenheit </label>
<input
type="number"
name="fahrenheit "
id="fahrenheit-input"
value={fahrenheit_value}
onChange={(e) => {
fahrenheit_to_celsius_converter(e);
}}
/>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
.container{
border:1px solid green;
width:30%;
height:30vh;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.container div{
display: flex;
flex-direction: column;
}
label{
font-size:20px;
text-transform: uppercase;
font-family: monospace;
}
#celsius-input,#fahrenheit-input{
padding:10px 20px;
text-align: center;
outline:none;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
CodePudding user response:
You can use the same onChange
handler but with a condition based on the current focused input:
const useState = React.useState
function App() {
// Use State
const [celsius_value, set_celsius_value] = useState(0);
const [fahrenheit_value, set_fahrenheit_value] = useState(0);
const [selected, setSelected] = useState("")
// state functions
const handleConversion = (e) => {
if(selected === "celsius"){
set_celsius_value(e.target.value);
set_fahrenheit_value(((e.target.value) * (9 / 5) 32).toFixed(1));
} else {
set_fahrenheit_value(e.target.value);
set_celsius_value(((e.target.value - 32) * (5 / 9)).toFixed(1));
// convert value
}
};
return (
<div className="container">
{/* Celsius */}
<div className="celsius-container">
<label htmlFor="celsius-input">celsius</label>
<input
type="number"
name="celsius"
id="celsius-input"
value={celsius_value}
onFocus={(e) => setSelected("celsius")}
onChange={handleConversion}
/>
</div>
{/* fahrenheit */}
<div className="fahrenheit -container">
<label htmlFor="fahrenheit -input">fahrenheit </label>
<input
type="number"
name="fahrenheit "
id="fahrenheit-input"
value={fahrenheit_value}
onFocus={(e) => setSelected("farenheit")}
onChange={handleConversion}
/>
</div>
</div>
);
}
ReactDOM.render(<App />, root)
.container{
border:1px solid green;
width:30%;
height:30vh;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.container div{
display: flex;
flex-direction: column;
}
label{
font-size:20px;
text-transform: uppercase;
font-family: monospace;
}
#celsius-input,#fahrenheit-input{
padding:10px 20px;
text-align: center;
outline:none;
}
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
CodePudding user response:
You need another function fahrenheit_to_celsius_converter
that is needs to be called when the fahrenheit input changes.
Note:
Don't coerce the input states to
Number
, let them be strings, otherwise the input might not work as expected.IMO clearing one input should also clear the other, check the early exit conditional in the snippet below.
const { useState } = React;
function App() {
// Use State
const [celsius_value, set_celsius_value] = useState("");
const [fahrenheit_value, set_fahrenheit_value] = useState("");
// state functions
const celsius_to_fahrenheit_converter = (e) => {
const celsius_input = e.target.value;
set_celsius_value(celsius_input);
if (celsius_input === "") {
set_fahrenheit_value("");
return;
}
const celsius_value = Number(celsius_input);
const fahrenheit_value = String((celsius_value * 9) / 5 32);
set_fahrenheit_value(fahrenheit_value);
};
const fahrenheit_to_celsius_converter = (e) => {
const fahrenheit_input = e.target.value;
set_fahrenheit_value(fahrenheit_input);
if (fahrenheit_input === "") {
set_celsius_value("");
return;
}
const fahrenheit_value = Number(fahrenheit_input);
const celcius_value = String(((fahrenheit_value - 32) * 5) / 9);
set_celsius_value(celcius_value);
};
return (
<div className="container">
{/* Celsius */}
<div className="celsius-container">
<label htmlFor="celsius-input">celsius</label>
<input
type="number"
name="celsius"
id="celsius-input"
value={celsius_value}
onChange={(e) => {
celsius_to_fahrenheit_converter(e);
}}
/>
</div>
{/* Fahrenheit */}
<div className="fahrenheit-container">
<label htmlFor="fahrenheit-input">fahrenheit </label>
<input
type="number"
name="fahrenheit "
id="fahrenheit-input"
value={fahrenheit_value}
onChange={(e) => {
fahrenheit_to_celsius_converter(e);
}}
/>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
You can also do the same with a single handler using the name
attribute on the input elements.
const { useState } = React
function App() {
const [celsius_value, set_celsius_value] = useState("");
const [fahrenheit_value, set_fahrenheit_value] = useState("");
const converter = (e) => {
if (e.target.name === "celsius") {
const celsius_input = e.target.value;
set_celsius_value(celsius_input);
if (celsius_input === "") {
set_fahrenheit_value("");
return;
}
const celsius_value = Number(celsius_input);
const fahrenheit_value = String((celsius_value * 9) / 5 32);
set_fahrenheit_value(fahrenheit_value);
} else {
const fahrenheit_input = e.target.value;
set_fahrenheit_value(fahrenheit_input);
if (fahrenheit_input === "") {
set_celsius_value("");
return;
}
const fahrenheit_value = Number(fahrenheit_input);
const celcius_value = String(((fahrenheit_value - 32) * 5) / 9);
set_celsius_value(celcius_value);
}
};
return (
<div className="container">
{/* Celsius */}
<div className="celsius-container">
<label htmlFor="celsius-input">celsius</label>
<input
type="number"
name="celsius"
id="celsius-input"
value={celsius_value}
onChange={converter}
/>
</div>
{/* Fahrenheit */}
<div className="fahrenheit-container">
<label htmlFor="fahrenheit-input">fahrenheit </label>
<input
type="number"
name="fahrenheit"
id="fahrenheit-input"
value={fahrenheit_value}
onChange={converter}
/>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>