javascript - How to make setState take effect immediately? - Stack Overflow

There is an input element in my code:<input id="input" className="ml-2" type=&qu

There is an input element in my code:

<input id="input" className="ml-2" type="number" name="Qty" min="1" max="999" value={qty} onChange={(e) => {changeQty(e)}}/>

And the onChange handler is:

    const changeQty = (e) => {
        setQty(e.target.value);
        console.log(qty);
    }

So I suppose that whatever I enter in the input field will be printed out in the console, but the fact is there is delay.

For example, the default value is 1, then I type 2, then 1 will be printed out. Then I type 3, then 2 will be printed out. The number printed out is the previous one I entered instead of the current one, as shown below:

Could anyone tell me how to remove the delay?

I read useState set method not reflecting change immediately, but still cannot solve it.

I tried the code below as the answer indicates,

useEffect(() => {
    setQty(document.getElementById("input").value)
}, [qty]);

but an error ReferenceError: Cannot access 'qty' before initialization occurred.

Thanks!

There is an input element in my code:

<input id="input" className="ml-2" type="number" name="Qty" min="1" max="999" value={qty} onChange={(e) => {changeQty(e)}}/>

And the onChange handler is:

    const changeQty = (e) => {
        setQty(e.target.value);
        console.log(qty);
    }

So I suppose that whatever I enter in the input field will be printed out in the console, but the fact is there is delay.

For example, the default value is 1, then I type 2, then 1 will be printed out. Then I type 3, then 2 will be printed out. The number printed out is the previous one I entered instead of the current one, as shown below:

Could anyone tell me how to remove the delay?

I read useState set method not reflecting change immediately, but still cannot solve it.

I tried the code below as the answer indicates,

useEffect(() => {
    setQty(document.getElementById("input").value)
}, [qty]);

but an error ReferenceError: Cannot access 'qty' before initialization occurred.

Thanks!

Share Improve this question edited May 29, 2020 at 16:17 Snookums asked May 29, 2020 at 16:12 SnookumsSnookums 1,3605 gold badges25 silver badges54 bronze badges 3
  • Without the whole code it's impossible to answer this question. – Fez Vrasta Commented May 29, 2020 at 16:13
  • Where are you calling setState? A console.log outside the setState context will print the old value. – aksappy Commented May 29, 2020 at 16:17
  • 1 This boils down to the classic: "React setState is async" you have to use a callback or an effect to wait until the new state is set before using it. – DBS Commented May 29, 2020 at 16:23
Add a ment  | 

4 Answers 4

Reset to default 6

It's hard to say from the current question, but I'm going to assume that you're writing a function ponent and are using a useState hook. That is, somewhere above the changeQty you have something like:

const [qty, setQty] = useState(0);

If that's the case, then the answer is directly in the assignment of qty above. qty is set when you call the useState hook and will not change for the duration of the execution.

setQty does not update the value of qty. It updates the internal state, which will trigger a re-render. That means the next time your render function is invoked, qty will have the value you used.

But for the rest of the execution of the function, qty will remain whatever value it was when useState was called.

If you need the new value of qty in the same iteration of your function, you can capture that as a new variable.

const [qty, setQty] = useState(0);
let updatedQty = qty;

const changeQty = (e) => {
  updatedQty = e.target.value;
  setQty(updatedQty);
  console.log(updatedQty);
}

this.setState() has two forms that could help you here:

Functional Form

this.setState((prevState, props) => ({}))

Callback Form

this.setState(nextState, () => {
    // instructions for immediately-after the state update
})

It sounds like you could use the callback form here to defer some calculations into the callback.

Also, you can chain those if it's a warzone out there:

this.setState(nextState, () => {
    this.setState(nextState, () => {
        this.setState(nextState, () => {
            // you can do this, but probably don't
        })
    })
})

But, notice the extreme indenting that is occurring; it's reminiscent of callback hell and Promise christmas-tree hell.

The problem is that setQty is asynchronous. Try this:

useEffect(() => {
console.log(qty);

}, [qty]);

You will normally get current value in this console.log. In your code, your console.log may execute before the state is updated because setQty not synchronous as you may think

Since you didn't share all of your code, it's difficult to answer your question exactly, but it looks like you're using React's hooks, so I've created an example that uses hooks correctly to set the qty state and log the current qty value.

const Quantity = function() {
  const [qty, setQty] = React.useState(0);
  const changeQty = (e) => {
    setQty(e.target.value);
  };
  React.useEffect(() => {
    console.log(qty);
  }, [qty]);
  
  return (
      <input id="input" className="ml-2" type="number" name="Qty" min="1" max="999" value={qty} onChange={(e) => {changeQty(e)}}/>
  );
};
ReactDOM.render(<Quantity />, document.getElementById("app_root"));
<head>
  <script src="https://cdnjs.cloudflare./ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
  <script src="https://cdnjs.cloudflare./ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  <script src="https://cdnjs.cloudflare./ajax/libs/babel-core/5.8.25/browser-polyfill.min.js"></script>
</head>

<body>
  <div id="app_root"></div>
</body>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744771718a4592799.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信