I have 19 inputs and when one of them is changed, all the others reflect the change with a calculation.
<input value={mph} onChange={(e) => cmph(e.target.value, setKph, setMps)}
<input value={kph} onChange={(e) => ckph(e.target.value, setMph, setMps)}
<input value={mps} onChange={(e) => cmps(e.target.value, setKph, setMph)}
For each input I have one state. So I used 19 useState
variables. And all input have an onChange
.
const [mph, setMph] = useState() // miles per hour
const [kph, setKph] = useState() // kiliometers per hour
const [mps, setMps] = useState() // miles per seconds
So when any input is changed, it’s onChange
call its unique function do the calculation and set the state 18 times (for each of the other input).
Each input calls it’s own function that calculates the value of the others. Its simple math. No DB or endpoint calling.
function cmph(mph, setKph, setMps) {
const kph = mph * 1.60934
setKph(Math.round((kph + Number.EPSILON) * 100) / 100)
const mps = mph / 2.237
setMps(Math.round((mph + Number.EPSILON) * 100) / 100)
}
function ckph(kph, setMph, setMps) {
const mph = kph / 1.60934
setMph(Math.round((mph + Number.EPSILON) * 100) / 100)
const mps = mph / 2.237
setMps(Math.round((mps + Number.EPSILON) * 100) / 100)
}
function cmps(mps, setKph, setMph) {
const mph = mps * 2.237
setMph(mph)
const kph = mph * 1.60934
setKph(kph)
}
All I want is change any of the inputs and all others reflect the new value automatically.
PS: I reduced for three inputs so the example will be smaller. But I have 19 of these.
How can I solve this?
Stack Snippet:
const { useState } = React;
const Example = () => {
const [mph, setMph] = useState(); // miles per hour
const [kph, setKph] = useState(); // kiliometers per hour
const [mps, setMps] = useState(); // miles per seconds
function cmph(mph, setKph, setMps) {
const kph = mph * 1.60934;
setKph(Math.round((kph + Number.EPSILON) * 100) / 100);
const mps = mph / 2.237;
setMps(Math.round((mph + Number.EPSILON) * 100) / 100);
}
function ckph(kph, setMph, setMps) {
const mph = kph / 1.60934;
setMph(Math.round((mph + Number.EPSILON) * 100) / 100);
const mps = mph / 2.237;
setMps(Math.round((mps + Number.EPSILON) * 100) / 100);
}
function cmps(mps, setKph, setMph) {
const mph = mps * 2.237;
setMph(mph);
const kph = mph * 1.60934;
setKph(kph);
}
return (
<div>
<input
value={mph}
size="5"
onChange={(e) => cmph(e.target.value, setKph, setMps)}
/>
<input
value={kph}
size="5"
onChange={(e) => ckph(e.target.value, setMph, setMps)}
/>
<input
value={mps}
size="5"
onChange={(e) => cmps(e.target.value, setKph, setMph)}
/>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
2
Answers
There are tons of React-Ways to solve your issue.
One of those is using a Object with a key for each of your input/data-types.
Then
onChange
on of of the inputs, use adata-speed
attribute to see which value changed, set that 1:1 to the new state. For every other key in the state object, find your correctconvertFunction
and apply it as well.I’ve replaced all the
cmps
/ckph
functions with a simpleconvertFunction
to keep the demo clean.The problem is that your inputs are controlled, which means their values don’t automatically update unless you set the state member you’re using to set their
value
. The reason it works initially is that by not giving an initial value touseState
, you’re defaulting toundefined
, andvalue={undefined}
makes React think the input is uncontrolled. As soon as you change a value, the inputs go from uncontrolled to controlled, and it stops working. (If you use the development version of the React libs uring development, you’ll get a big warning about that.) More about controlled vs. uncontrolled inputs in the documentation.Instead:
useState
so that they don’t default toundefined
change
event of each input, update the state member that controls itFor instance, for
mph
:Working example (those default values may need tweaking):