使用挂钩时等待状态更新

时间:2019-03-15 02:07:35

标签: reactjs

如何等待使用Hooks更新状态。提交表单时,我需要在运行其他代码之前检查termsValidation是否为假。如果状态刚刚改变,它就不会改变。

import React, { useState } from 'react';

export default function Signup() {
  const [terms, setTerms] = useState('');
  const [termsValidation, setTermsValidation] = useState(false);

  function handleSubmit(e) {
    e.preventDefault();

    if (!terms) {
      setTermsValidation(true);
    } else {
      setTermsValidation(false);
    }

    if (!termsValidation) {
      console.log('run something here');
    }
  }

  return (
    <div>
      <form>
        <input type="checkbox" id="terms" name="terms" checked={terms} />

        <button type="submit" onClick={handleSubmit}>
          Sign up
        </button>
      </form>
    </div>
  );
}

3 个答案:

答案 0 :(得分:0)

当然。像setTermsValidation这样的状态更改是异步操作,这意味着它不是立即执行的,程序不会等待它。它会触发并忘记。因此,当您调用setTermsValidation(true)时,程序将继续运行下一个块,而不是等待termValidation更改为true。因此,termsValidation仍然具有旧值。

您可以这样做

function handleSubmit(e) {
    e.preventDefault();

    if (!terms) {
      setTermsValidation(true);
    } else {
      setTermsValidation(false);
      // assuming you want to run something when termsvalidation turn to false
      console.log('run something here');
    }
}

或者最好使用钩子useEffect()

useEffect(() => {
    if (!termsValidation) {
      console.log('run something here');
    }
}, [termsValidation]);

但是请小心,因为useEffect也会在初始渲染上运行。

答案 1 :(得分:0)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using LayoutSample.Models; using LayoutSample.Presenters; using LayoutSample.Views; namespace LayoutSample { public partial class Form1 : Form, IFlowLabel { public Form1() { InitializeComponent(); } string IFlowLabel.label { get { return flowLayoutPanel1.ToString(); } set { if (flowLayoutPanel1.InvokeRequired) { flowLayoutPanel1.Invoke(new MethodInvoker(() => { flowLayoutPanel1.Text = value; })); } else { flowLayoutPanel1.Text = value; } } } private void Form1_Load(object sender, EventArgs e) { for (int i = 0; i < 100; i++) { Label label = new Label(); label.AutoSize = false; label.Width = 50; label.Text = i.ToString(); flowLayoutPanel1.Controls.Add(label); } DataPresenter presenter = new DataPresenter(this); presenter.CalculateArea(); } } } 钩子是异步的,但没有useState那样的回调API。如果要等待状态更新,则需要一个setState钩子:

useEffect

答案 2 :(得分:0)

在这种情况下,不要忘记 useRef 作为一种可能性——useState 和 useEffect 当然有它们的位置,但是你跟踪和管理状态的逻辑可能有点麻烦,并且可能会导致不必要的重新——渲染您的组件(当该状态不构成渲染输出的一部分时)。作为来自 OP 的示例:

import React, { useState, useRef } from 'react';

export default function Signup() {
  const [terms, setTerms] = useState('');
  const termsValidation = useRef(false);

  function handleSubmit(e) {
    e.preventDefault();

    if (!terms && !termsValidation.current) {
      termsValidation.current = true;
      console.log('run something here');
      termsValidation.current = false; // when its finished running
    }
 }

  return (
    <div> etc
  );
}