You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何子组件触发的setState内console.log能获取更新后状态?

React状态更新后console.log输出差异的原因

CASE 1:状态更新后输出旧值

在titleChangeHandler中调用setCurrentTitle后,立即console.log(currentTitle)会输出旧的状态值。

import "./ExpenseForm.css";
import { useState } from "react";

const ExpenseForm = (props) => {
  const [currentTitle, setCurrentTitle] = useState("");
  const [currentAmount, setCurrentAmount] = useState("");
  const [currentDate, setCurrentDate] = useState("");

  const titleChangeHandler = (event) => {
    setCurrentTitle(event.target.value);
    console.log(currentTitle); // 输出旧值
  };

  const amountChangeHandler = (event) => {
    setCurrentAmount(event.target.value);
  };

  const dateChangeHandler = (event) => {
    setCurrentDate(event.target.value);
  };

  const submitHandler = (event) => {
    event.preventDefault();

    const expenseData = {
      title: currentTitle,
      amount: currentAmount,
      date: currentDate,
    };

    props.onSaveExpenseData(expenseData);

    setCurrentAmount("");
    setCurrentTitle("");
    setCurrentDate("");
  };

  return (
    <form onSubmit={submitHandler}>
      <div className="new-expense__controls">
        <div className="new-expense__control">
          <label>Title</label>
          <input
            type="text"
            value={currentTitle}
            onChange={titleChangeHandler}
          />
        </div>
        <div className="new-expense__control">
          <label>Amount</label>
          <input
            type="number"
            min="0.1"
            step="0.1"
            value={currentAmount}
            onChange={amountChangeHandler}
          />
        </div>
        <div className="new-expense__control">
          <label>Date</label>
          <input
            type="date"
            min="2019-01-01"
            max="2022-12-31"
            value={currentDate}
            onChange={dateChangeHandler}
          />
        </div>
      </div>
      <div className="new-expense__actions">
        <button type="submit">Add expense</button>
      </div>
    </form>
  );
};

export default ExpenseForm;

CASE 2:状态更新后输出新值

将onSelectYear函数通过props传给子组件ExpensesFilter,在子组件中调用该函数时,内部setYear后console.log(year)会输出最新值。

Expenses.js

import "./Expenses.css";
import ExpenseItem from "./ExpenseItem";
import React, { useState } from "react";
import ExpensesFilter from "./ExpenseFilter";
import Card from "../UI/Card";

const Expenses = (props) => {
  const [year, setYear] = useState("2020");
  const onSelectYear = (year) => {
    setYear(year);
    console.log(year); // 输出新值
  };
  return (
    <div>
      <Card className="expenses">
        <ExpensesFilter
          selectedYear={year}
          onSelectYear={onSelectYear}
        ></ExpensesFilter>
        {props.expenses.map(expense => (
          <ExpenseItem
            key={expense.id}
            title={expense.title}
            amount={expense.amount}
            date={expense.date}
          />
        ))}
      </Card>
    </div>
  );
};

export default Expenses;

ExpenseFilter.js

import React from "react";
import "./ExpenseFilter.css";

const ExpensesFilter = (props) => {
  const onSelectChange = (event) => {
    props.onSelectYear(event.target.value);
  };
  return (
    <div className="expenses-filter">
      <div className="expenses-filter__control">
        <label>Filter by year</label>
        <select value={props.selectedYear} onChange={onSelectChange}>
          <option value="2022">2022</option>
          <option value="2021">2021</option>
          <option value="2020">2020</option>
          <option value="2019">2019</option>
        </select>
      </div>
    </div>
  );
};

export default ExpensesFilter;

差异原因

核心区别在于你打印的不是同一个对象:

  1. CASE 1:你打印的是组件的状态变量currentTitle。React的状态更新是异步且批量调度的,当前事件处理函数执行期间,状态变量还未更新——因为函数闭包捕获的是更新前的状态值,所以打印出旧值。

  2. CASE 2:你打印的是onSelectYear函数的参数year,这个参数是子组件传过来的event.target.value(即最新选中的年份),和React的状态更新异步性完全无关。你只是把这个参数传给setYear,然后直接打印参数本身,自然是最新值。

如果把CASE 2的代码改成打印组件的状态变量year,结果就会和CASE 1一致:

const onSelectYear = (newYear) => {
  setYear(newYear);
  console.log(year); // 这里打印状态变量,会输出旧值
};

内容的提问来源于stack exchange,提问作者Jatin Damariya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:45:50