The problem with the onChange event is, it is providing the value but with one character less.
Example : if I type "overflow" in the input box, the provided value will be "overflo" (without w).
It’s not registering the last character input.
How can i get the full text from the input field. Is there any other way to solve this problem.
import React, {useState} from "react";
function Average() {
const [totalVal, setTotalVal] = useState("");
const [shares, setShares] = useState("");
const handleKeyDown = (event) => {
if (event.key === 'Enter') {
setTotalVal(totalVal + "+");
}
};
const calcAvg = (event) => {
let avg = eval(totalVal) / shares;
document.getElementById("avgBox").innerHTML = ": ₹" + avg.toFixed(2);
event.preventDefault();
};
return (
<>
<div>
<div className="my-4">
<label className="block">
<input
type="number"
id="totalShares"
className="mt-1 px-3 py-2 bg-white border shadow-sm border-slate-300 placeholder-slate-500 focus:outline-none focus:border-slate-300 focus:ring-slate-300 block w-full rounded-md sm:text-sm focus:ring-1"
placeholder="Enter number of stocks"
value={shares}
onChange={(event) => setShares(event.target.value)}
/>
</label>
</div>
<div className="my-4">
<label className="block">
<input
type="text"
id="stockVal"
value={totalVal}
className="mt-1 px-3 py-2 bg-white border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none focus:border-slate-300 focus:ring-slate-300 block w-full rounded-md sm:text-sm focus:ring-1"
placeholder="Enter price of every stock with + in between"
autoComplete="off"
onChange={(event) => {setTotalVal(event.target.value); calcAvg()}}
onKeyDown={handleKeyDown}
/>
</label>
</div>
<div
className="p-2 my-8 unselectable cursor-pointer flex w-full justify-center bg-green-400 hover:bg-green-500 text-white font-medium rounded"
onClick={calcAvg}>
Average Price<div id="avgBox"></div>
</div>
</div>
</>
);
}
export default Average;
2
Answers
Here is an example of getting input values with
useRef()
hook.CodeSandbox:
https://codesandbox.io/s/kind-framework-ge6w2e?file=/src/App.js
The problem is that you
setTotalVal
and immediately callcalcAvg
. Since setState is sort of async this function won’t have the updated value until the next render.You can fix this by using another state in combination with a
useEffect
. We’ll createaverageValue
state to store the average value. Then we add theuseEffect
to run whenever thetotalVal
or theshares
change. Instead of thedocument.getElementBy
we can simply display the average value the React way.I removed the
calcAvg
since we don’t need it anymore when using the new functionality.Note: It is not recommended to manipulate the DOM using
document.getElementBy...
.Side note: Although eval works, I suggest you try and take a look into storing your stock prices and amounts within some kind of array. This way you can, in the future, for example list all of you stocks.