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

React.js中numOfI状态无修改时两次console.log结果大幅差异问题

问题根源

1. 核心反模式:不要在State中存储组件实例

React的state设计用来存储纯数据,而非渲染好的组件实例。你当前把<IngredientInput />实例存在numOfI state中,直接导致了闭包陷阱:
你每次调用handleAdditionalIngredient生成新组件时,绑定的handleRemoveIngredient是当时渲染闭包中的函数,函数内部捕获的numOfI是组件创建时刻的旧状态值,而非最新状态。你点击删除按钮时触发的是旧闭包里的函数,打印的自然是旧的numOfI值,和当前最新状态不一致,就会出现「状态自行更新」的错觉。

2. 浏览器控制台的引用类型打印坑

你打印的数组是引用类型,浏览器控制台不会在打印时刻快照保存对象内容,只会在你手动展开数组时才读取当前内存中的值,进一步混淆了你的判断。如果要查看打印时刻的真实值,改成console.log(JSON.parse(JSON.stringify(numOfI)))即可验证。

3. 表单状态处理逻辑错误

你当前的handleChange写法无法正确更新formState里的ingredients数组:直接用[event.target.name]作为key赋值,不会修改数组中对应索引的对象属性,后续提交表单也拿不到正确的配料数据。


修复方案

直接复用你已经存在的formState.ingredients数组控制渲染,完全可以删掉多余的numOfI state:

import { useState } from 'react';
import { createRecipe } from '../services/recipeService';
import IngredientInput from '../componenets/IngredientInput';

export default function RecipeNew(props) {
    const [formState, setFormState] = useState({
        creator: '',
        access: '',
        name: '',
        ingredients: [{ amount: '', ingred: '' }],
        steps: []
    });

    async function handleSubmit(event) {
        event.preventDefault();
        createRecipe(formState);
        setFormState({
            creator: '',
            access: '',
            name: '',
            ingredients: [{ amount: '', ingred: '' }],
            steps: []
        });
        props.history.push('/home');
    }

    // 配料项变更处理
    function handleIngredientChange(index, field, value) {
        const newIngredients = [...formState.ingredients];
        newIngredients[index][field] = value;
        setFormState({...formState, ingredients: newIngredients});
    }

    // 新增配料
    function handleAdditionalIngredient() {
        setFormState({
            ...formState,
            ingredients: [...formState.ingredients, { amount: '', ingred: '' }]
        });
    }

    // 删除配料
    function handleRemoveIngredient(index) {
        const newIngredients = formState.ingredients.filter((_, i) => i !== index);
        setFormState({...formState, ingredients: newIngredients});
    }

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <div className='ingred'>
                    <input type='text' name='name'
                        placeholder='Name' 
                        onChange={e => setFormState({...formState, name: e.target.value})} />

                    {/* 直接根据ingredients数组渲染组件,不需要额外state存组件 */}
                    {formState.ingredients.map((item, index) => (
                        <IngredientInput 
                            key={index}
                            first={index === 0}
                            amount={item.amount}
                            ingred={item.ingred}
                            onChange={(field, value) => handleIngredientChange(index, field, value)}
                            onRemove={() => handleRemoveIngredient(index)}
                        />
                    ))}

                    <button type="button" onClick={handleAdditionalIngredient}>+</button>
                </div>

                <div className='steps'>
                    <textarea cols="40" rows="5" name='steps[]' placeholder={`Step 1`} />
                </div>
                <button>Submit</button>
            </form>
        </div>
    );
}

对应修改IngredientInput组件:

export default function IngredientInput(props){
    return(
        <div>
            <input 
                type='text' 
                value={props.amount}
                onChange={e => props.onChange('amount', e.target.value)} 
                placeholder='#'
            />
            <input 
                type='text' 
                value={props.ingred}
                onChange={e => props.onChange('ingred', e.target.value)} 
                placeholder='Ingredient'
            />
            {!props.first && <button onClick={props.onRemove} type='button'>-</button>}  
        </div>
    );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 15:39:04