skip to Main Content

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


  1. Here is an example of getting input values with useRef() hook.

    const ref = useRef();
      const handleChange = () => {
        console.log(ref.current.value);
      };
      return (
        <div className="App">
          <h2>I'm trying to get input value</h2>
    
          <input
            type="text"
            ref={ref}
            onChange={handleChange}
            placeholder="type something..."
          />
        </div>
      );
    

    CodeSandbox:
    https://codesandbox.io/s/kind-framework-ge6w2e?file=/src/App.js

    Login or Signup to reply.
  2. The problem is that you setTotalVal and immediately call calcAvg. 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 create averageValue state to store the average value. Then we add the useEffect to run whenever the totalVal or the shares change. Instead of the document.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....

    import React, { useState, useEffect } from "react";
    
    function Average() {
      const [totalVal, setTotalVal] = useState("");
      const [shares, setShares] = useState("");
      const [averageValue, setAverageValue] = useState(0);
    
      const handleKeyDown = (event) => {
        if (event.key === "Enter") {
          setTotalVal(totalVal + "+");
        }
      };
    
      useEffect(() => {
        const avg = eval(totalVal) / shares;
        setAverageValue(avg);
      }, [totalVal, shares]);
    
      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);
                  }}
                  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">
              Average Price: ₹ {averageValue.toString()}
            </div>
          </div>
        </>
      );
    }
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search