how to get current value from input field in react js

Viewed 380

I am trying to get current value from input field, but after onclick I am getting preious value in colsole. here is my code

    import { React, useState } from "react";

const CompoundIntrest = () => {
  const [capitalValue, setcapitalValue] = useState(1000);
  const ChangeCapital = () => {
    setcapitalValue(capitalValue - 100);
  };
  const Calculate = () => {
    console.log(capitalValue);
  };

  return (
    <>
      <button
        onClick={() => {
          ChangeCapital();
          Calculate();
        }}
      >
        click
      </button>
      <input type="number" value={capitalValue} />
    </>
  );
};

export default CompoundIntrest;
6 Answers

State updates occur asynchronously, so you won't have the updated state value inside the event handler.

You can lift the new value i.e. capitalValue - 100 to a scope from where it can be passed down to both ChangeCapital & Calculate.

const CompoundIntrest = () => {
  const [capitalValue, setCapitalValue] = React.useState(1000);

  const handleClick = () => {
    const newCapitalValue = capitalValue - 100;
    ChangeCapital(newCapitalValue);
    Calculate(newCapitalValue);
  };
  const ChangeCapital = (capitalValue) => {
    setCapitalValue(capitalValue);
  };
  const Calculate = (capitalValue) => {
    console.log(capitalValue);
  };

  return (
    <React.Fragment>
      <button onClick={handleClick}>click</button>
      <input
        type="number"
        value={capitalValue}
        onChange={(e) => setCapitalValue(e.target.value)}
      />
    </React.Fragment>
  );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<CompoundIntrest />);
<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>
<div id="root"></div>

Note: The state updater function is called synchronously but the state updates happen asynchronously.

This becomes more clear if you update the state by passing a state updater callback, you would see that the callback is fired synchronously. Notice the order of logs in the example below:

function App() {
  const [count, setCount] = React.useState(0);

  const handleClick = () => {
    console.log("Before calling setCount");
    setCount((currCount) => {
      console.log("Inside setCount");
      return currCount + 1;
    });
    console.log("After calling setCount");
  };

  return <button onClick={handleClick}>Count: {count}</button>;
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<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>
<div id="root"></div>

I think, you should add onChange method in input tag like below:

Then you get current value in onClick event in button tag.

import { React, useState } from "react";

const CompoundIntrest = () => {
  const [capitalValue, setcapitalValue] = useState(1000);
  const ChangeCapital = () => {
    setcapitalValue(capitalValue - 100);
  };
  

  useEffect(() => {
    const Calculate = () => {
      console.log(capitalValue);
    };
    Calculate()
  }, [capitalValue])
  

  return (
    <>
      <button
        onClick={() => {
          ChangeCapital();
        }}
      >
        click
      </button>
      <input type="number" value={capitalValue} onChange={(e) => setcapitalValue(e.target.value)} />
    </>
  );
};

export default CompoundIntrest;

You can use Use useEffect Like this:-

import React,{useState,useEffect} from "react";

const CompoundIntrest  = () => {
  const [capitalValue, setcapitalValue] = useState(1000);
  const ChangeCapital = () => {
    setcapitalValue(capitalValue - 100);
  };
  const Calculate = () => {
    console.log(capitalValue);
  };
  useEffect(()=>{
    console.log("afet chage",capitalValue);
  },[capitalValue]);
  return (
    <>
    <button
        onClick={() => {
          ChangeCapital();
          Calculate();
        }}
      >
        click
      </button>
      <input type="number" value={capitalValue} />
    </>
  );
};

You can use the onChange event in the input field to get current value.

const [currentValue, setCurrentValue] = useState['']

const changeHandler = (e:any) => {
  e.preventDefault();
  const { value } = e.target
  console.log('value', value);
  setCurrentValue(value)
}
<input type="string" value={currentValue} onChange={(e:any) => changeHandler(e)}/>

In the case of controlled component, other members have already provided the answer, I just want to give you an idea about uncontrolled component.

Assuming that we are dealing with an uncontrolled component ( "input" element ) then how we can get the value.

    1. import { React, useState, useRef, useEffect } from "react";
    2. 
    3. const CompoundIntrest = () => {
    4. const [capitalValue, setcapitalValue] = useState(1000);
    5. const inputRef = useRef(null);
    6. 
    7. useEffect(() => {
    8.  console.log(capitalValue);
    9. }, [capitalValue]);
   10.
   11. const ChangeCapital = () => {
   12.   setcapitalValue(inputRef.current.value - 100);
   13. };
   14. 
   15. return (
   16.   <>
   17.     <button onClick={ChangeCapital}>click</button>
   18.     <input ref={inputRef} type="number" />
   19.   </>
   20.  );
   21. };
   22. 
   23. export default CompoundIntrest;

At line 5, we have created a ref with initial value null using useRef hook of react, which later will be used to store reference of input element.

At line 18, we have assigned the inputRef to the ref of input element, which will be use to get the value from the field.

At line 12, we are getting the value of input as inputRef.current.value .

To check the update in the value of capitalValue state onClick event of button we can use useEffect hook of react ( From Line 7 to Line 9 is doing the same ).

PS : Please let me know if this clear your doubt or not. Thanks for reading the answer.

your code is fine, and your state is successfuly updated, the problem is the timing of calling your console. react handles your code async, it means it starts your changeCapital, and before the change capital function is finished it calls the calculate function, so the value of your state, is the previous value.

you need to call your calculate function somewhere else:

  1. you can call it in a UseEffect hook, this way your function gets called whenever your state has successfuly changed, or

  2. you can call your calculate in 'onchange' event of your input feild

if you want the better solution, the first one is more reactly than the second one

Related