Home > Back-end >  how to switch between inputs in converter app in react?
how to switch between inputs in converter app in react?

Time:05-07

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>

  • Related