如何在 React 回调函数闭包中使用当前状态

问题描述 投票:0回答:1

我正在制作一个带有动态表单输入列表的网页,可以使用按钮添加或删除更多输入字段。我有一个父对象

<Ingredients />
,它跟踪输入并将它们作为子组件列表
<Ingredient />
保持在某种反应状态。每个
<Ingredient />
子级都有一个删除按钮,用于将它们从列表中删除,并传递一个函数回调
DeleteInput
,作为父级在单击时删除它们的道具。

问题是,当按下删除按钮时,该输入之后的所有字段也会消失。似乎是因为当调用回调时,函数内

inputList
的值是组件首次创建时的值。我怀疑
DeleteInput
函数是子组件闭包的一部分,即使它位于父组件中?

图像中显示的打印语句的输出突出了这一点。即使有 3 个输入形式,内部函数也只能看到第一个,因为这是创建时

inputList
的状态。

如何修复此错误,以便

inputList
函数内使用的
DeleteInput
的值是最新状态?我尝试使用react useCallback钩子,并将
inputList
作为依赖项,但它有同样的问题。

// Parent
export function Ingredients() {

    const [inputList, setInputList] = useState([]);
    const [key, setKey] = useState(1);

    function AddInput() {
        setInputList(inputList.concat([<Ingredient 
            key={key}
            index={key}
            deleteInput={deleteInput}
        />]))
        setKey(key+1);
    }

    // Approach 1 with regular function
    function DeleteInput() {
        console.log("Inside"); 
        console.log(inputList);
        let tmp = inputList;
        tmp.splice(indexToDel, 1)
        setInputList(tmp);
    }

    // Approach 2 with useCallback hook
    const DeleteInput = useCallback((indexToDel) => {
        console.log("Inside"); 
        console.log(inputList);
        let tmp = inputList;
        tmp.splice(indexToDel, 1)
        setInputList(tmp);
    }, [inputList])

    console.log("Outside"); 
    console.log(inputList);

    return (
        <div>
            {inputList}
            <button type='button' onClick={AddInput}>Add More</button>
        </div>
    )
}

// Child
function Ingredient({index, deleteInput}) {

    const i = index;

    return (
        <div className={styles.ingredient}>
            <input className={styles.ingredientname} type='text' placeholder='Ingredient'></input>
            <button type='button' onClick={() => DeleteInput(index)}>X</button>
        </div>
    )
} 

添加 3 个输入并删除第 2 个输入时打印语句输出

javascript reactjs web next.js
1个回答
0
投票
Approach 1: Using a regular function:

function DeleteInput(indexToDel) {
    console.log("Inside");
    console.log(inputList);
    let tmp = [...inputList]; // Create a copy of inputList
    tmp.splice(indexToDel, 1);
    setInputList(tmp);
}

方法2:使用useCallback钩子:

const DeleteInput = useCallback((indexToDel) => {
    console.log("Inside");
    console.log(inputList);
    let tmp = [...inputList]; // Create a copy of inputList
    tmp.splice(indexToDel, 1);
    setInputList(tmp);
},

[输入列表]);

© www.soinside.com 2019 - 2024. All rights reserved.