输入字段始终是我输入内容的一个值

Input field is always one value behind what Ive typed

我第一次尝试构建日期输入。如果月份或日期设置为单个数字,我的任务是确保输入显示前导 0。我遇到的问题是,当输入一个值时,它不会进入下一个处理程序,直到我下次在字段中键入时。我相信这是因为我通过状态传递价值。但我不确定如何在用户在字段中键入内容后立即发送状态:

州:

  const [date, setDate] = useState({ day: "", month: "", year: "" });

我的日期输入由三个单独的输入组成 mon/day/year 我在这里只显示月份:

<div className="nh-date">
          <Input
            onChange={dateChange("month")}
            value={date.month}
            className={`nh-mon ${!!error && "error"}`}
            name="month"
            id="mon"
            maxLength={2}
            type="number"
            selectTextOnFocus={true}
          />
          <span className="sep">/</span>

使用效果:


useEffect(() => {
    if (!!effectiveDate) {
      const effectiveMoment = !!effectiveDate ? moment.parseZone(effectiveDate) : {};
      setCalendarDate(effectiveMoment);
    }

    if (!!startDate) {
      const [month, day, year] = startDate.split("/");
      let shortYear = year.slice(-2);
      setDate({ ...date, day: day, month: month, year: shortYear });

      const newDate = `${month}/${day}/${year}`;
      if (moment(newDate).isValid()) {
        debounceCallback(handleDateInputChange, newDate);
        setError(false);
      } else {
        setError(true);
      }
    }
  }, [startDate, effectiveDate]);

我的 onChange 处理程序如下所示:

     const dateChange = (field: string) => (e: any) => {
        // format to fit
        let value = e.target.value;
        let d = { day: "", month: "", year: "" };
        if (value.length < 2) {
          value = "0" + value;
        } else {
          //remove extra leading 0's
          value = value.slice(-2);
        }
    
        setDate({ ...date, [field]: value });
        const newDate = `${date.month}/${date.day}/20${date.year}`;
        setStartDate(newDate);
      };

一旦我在字段中输入 debounceCallback(handleDateChange, newDate); 就会收到 newDate 但不是当前显示的那样,它会发送初始值或先前的值。我仍然在努力处理状态下的输入,我不确定如何解决这个问题,任何建议都会有所帮助。谢谢!

在 useEffect 中,你的日期已更新,你用新日期调用回调

const dateChange = (field: string) => (e: any) => {
    // format to fit
    let value = e.target.value;
    let d = { day: "", month: "", year: "" };
    if (value.length < 2) {
      value = "0" + value;
    } else {
        //remove extra leading 0's
      value = value - 0;
    }

    setDate((prevState) => {
        return { ...prevState, [field]: value };
    });
}

useEffect(() => {
  const newDate = `${date.month}/${date.day}/${date.year}`;
  if (moment(newDate).isValid()) {
    debounceCallback(handleDateChange, newDate);
    setError(false);
  } else {
    setError(true);
  }
}, [date, //rest dependencies]);

出于各种原因(主要是性能),在 React 中调用 setState() 是异步的。在幕后,React 会将对 setState() 的多次调用分批处理为单个状态突变,然后一次重新渲染组件,而不是为每个状态更改重新渲染。

I think you get previous value for Month 
setDate({ ...date, [field]: value }); not immediately update the state.

const dateChange = (field: string) => (e: any) => {
    // format to fit
    let value = e.target.value;
    let d = { day: "", month: "", year: "" };
    if (value.length < 2) {
      value = "0" + value;
    } else {
        //remove extra leading 0's
      value = value - 0;
    }

    setDate({ ...date, [field]: value });

    const newDate = `${value}/${date.day}/${date.year}`;
   
    if (moment(newDate).isValid()) {
      debounceCallback(handleDateChange, newDate);
      setError(false);
    } else {
      setError(true);
    }
  };