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

首次点击时useState钩子设置taskID返回undefined问题求助

解决useState设置taskID首次点击返回undefined的问题

我在使用useState钩子设置taskID时遇到问题:首次点击按钮会返回undefined,但刷新整个页面后就能正常运行。怀疑问题出在嵌套数组的映射方式上,代码如下:

const [task_id, setGetid] = useState('')

return (
    <div>
        {cart && Object.keys(cart).map(state => {
            return (
                <div className='h-auto max-h-[60vh] w-[50vw] overflow-y-auto flex flex-row flex-wrap justify-center items-center mt-5 gap-4' key={cart[state]._id}>
                    {cart[state]?.list && Object.keys(cart[state]?.list).map(task => {
                        return (
                            <div className='bg-[#1c1e21] h-[6vh] w-[48vw] relative drop-shadow-md flex flex-row items-center justify-end' key={cart[state]?.list[task]?._id}>
                                <span className='ml-5 text-white font-Poppins text-1xl absolute left-0'>{cart[state]?.list[task]?.task}</span>
                                <form onSubmit={handleSubmit(patchHandler)}>
                                    <button type='submit' className='bg-[#01313d] text-md font-Poppins text-white drop-shadow-md h-[4vh] w-auto flex flex-row items-center pl-3 pr-3 mr-2 gap-1'>
                                        <FaEdit /> Edit
                                    </button>
                                </form>
                                <form onSubmit={deleteHandler}>
                                    <button type='submit' onClick={() => {
                                        setGetid(cart[state]?.list[task]?._id) // 首次点击时设置task ID返回undefined,刷新页面后可正常工作
                                    }} className='bg-[#01313d] text-md font-Poppins text-white drop-shadow-md h-[4vh] w-auto flex flex-row items-center pl-3 pr-3 mr-2 gap-1'>
                                        <FaTrash /> Remove
                                    </button>
                                </form>
                            </div>
                        )
                    })}
                </div>
            )
        })}
    </div>
)

问题原因

  1. 首次渲染时cart数据可能未完全加载,虽然做了空值判断,但嵌套层级的cart[state]?.list[task]?._id在数据未就绪时会返回undefined。
  2. useState的更新是异步的,点击按钮时onClick触发setGetid,但表单的onSubmit会立即执行,此时task_id还没更新,导致deleteHandler拿到旧值undefined。

解决方案

方案1:直接传ID给删除函数(最推荐)

不用通过useState存task ID,点击时直接把ID作为参数传给deleteHandler,绕开异步更新的问题:

<form onSubmit={(e) => {
    e.preventDefault();
    const taskId = cart[state]?.list[task]?._id;
    deleteHandler(taskId);
}}>
    <button type='submit' className='bg-[#01313d] text-md font-Poppins text-white drop-shadow-md h-[4vh] w-auto flex flex-row items-center pl-3 pr-3 mr-2 gap-1'>
        <FaTrash /> Remove
    </button>
</form>

对应的删除函数修改为:

const deleteHandler = (taskId) => {
    if (!taskId) return;
    // 这里执行你的删除逻辑,比如调用API
};

方案2:确保数据加载完成后再渲染

给组件加加载状态,等cart数据完全获取后再渲染列表,避免渲染未就绪的数据:

const [loading, setLoading] = useState(true);
const [cart, setCart] = useState({});

// 假设这里是获取cart数据的逻辑
useEffect(() => {
    const fetchCart = async () => {
        const res = await fetch('/your-cart-api');
        const data = await res.json();
        setCart(data);
        setLoading(false);
    };
    fetchCart();
}, []);

if (loading) return <div>加载中...</div>;

// 后面再渲染原来的cart列表

方案3:用useRef保存最新ID

如果一定要用useState存ID,可以搭配useRef确保删除函数能拿到最新值:

const [task_id, setGetid] = useState('');
const taskIdRef = useRef('');

// 点击时同时更新state和ref
<button type='submit' onClick={() => {
    const id = cart[state]?.list[task]?._id;
    setGetid(id);
    taskIdRef.current = id;
}}>...</button>

// 删除函数里用ref的值
const deleteHandler = (e) => {
    e.preventDefault();
    const currentId = taskIdRef.current;
    if (currentId) {
        // 执行删除逻辑
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:15:33