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

React开发Todo列表时,console.log打印数组总是缺失最后一项的原因是什么?

问题原因与解决方案

这个问题我刚入门React的时候也踩过坑!核心原因是React的useState状态更新是异步的,咱们一步步拆解:

为什么打印的数组总是少最后一项?

当你调用setItems(prev => [...prev, value])时,React并不会立刻修改items变量的值——它会把这次更新操作加入到一个更新队列中,等到当前函数执行完毕、浏览器准备重新渲染组件的时候,才会批量处理队列里的更新,真正更新items的状态。

所以你在setItems之后立刻执行console.log(items),拿到的其实是更新前的旧状态:

  • 第一次添加"bread":setItems把空数组更新为["bread"],但此时items还是旧的空数组,所以控制台打印空数组;
  • 第二次添加"milk":setItems把["bread"]更新为["bread", "milk"],但此时items还是旧的["bread"],所以控制台只打印这一项。

怎么拿到最新的状态并打印?

这里有两种常用的解决方案:

方案1:用useEffect监听状态变化

通过useEffect钩子监听items的变化,当items真正更新完成后,再执行打印操作:

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

export default function App() {
  const [items, setItems] = useState([]);
  const inputRef = useRef();

  // 监听items变化,更新后打印
  useEffect(() => {
    console.log("最新的items数组:", items);
  }, [items]); // 依赖项设为items,只有items变化时才触发

  function onSubmit(e) {
    e.preventDefault();
    const value = inputRef.current.value;
    setItems(prev => [...prev, value]);
    inputRef.current.value = "";
  }

  // 其余代码不变...
}

方案2:在setItems的更新函数中打印新值

如果你只是想确认本次更新后的数组内容,可以直接在setItems的回调函数里处理——因为这里的prev是更新前的状态,我们可以先创建新数组,打印后再返回:

function onSubmit(e) {
  e.preventDefault();
  const value = inputRef.current.value;
  setItems(prev => {
    const newItems = [...prev, value];
    console.log("本次更新后的数组:", newItems); // 这里拿到的是最新值
    return newItems;
  });
  inputRef.current.value = "";
}

额外小建议:优先使用受控组件

你的代码里用useRef获取输入框值是可行的,但React更推荐受控组件的写法——用useState管理输入框的状态,这样不需要依赖ref,代码更符合React的状态管理逻辑:

import { useState } from "react";

export default function App() {
  const [items, setItems] = useState([]);
  const [inputValue, setInputValue] = useState(""); // 用state管理输入值

  function onSubmit(e) {
    e.preventDefault();
    if (inputValue.trim()) { // 可以加个非空判断
      setItems(prev => [...prev, inputValue]);
      setInputValue(""); // 清空输入框直接更新state
    }
  }

  return (
    <main>
      <form onSubmit={onSubmit}>
        {/* 受控组件:value绑定state,onChange更新state */}
        <input 
          type="text" 
          value={inputValue} 
          onChange={(e) => setInputValue(e.target.value)} 
        />
        <button type="submit">Add</button>
      </form>
      <h3>My List:</h3>
      <ul>
        {items.map((item, index) => (
          <li key={index}>{item}</li> {/* 注意要加key属性哦 */}
        ))}
      </ul>
    </main>
  );
}

(另外别忘了给map渲染的li加key属性,这是React列表渲染的要求)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 13:42:41