首页 > 解决方案 > 多次使用 useState 更新列表会导致错误输出

问题描述

我正在努力处理 React 中的 useState 列表。我必须连续两次将一个项目添加到列表中,并且只添加第二个项目。编码:

应用程序.js

import React, { useState } from "react";
import ItemForm from "./itemForm";

function App() {
  const [itemList, setItemList] = useState([]);

  function addItem(item) {
    setItemList([...itemList, item]);
  }

  return (
    <div>
      <ItemForm onAddItem={ addItem } />
      { itemList && 
          itemList.map((item, i) => <ul key={ i + itemList } >{ item }</ul>) }
    </div>
  );
}

export default App;

ItemForm.js

import React, { useState } from 'react';

function ItemForm({ onAddItem }) {
    const [inputValue, setInputValue] = useState('');

    function handleSubmit(e) {
        e.preventDefault();
        var item = e.target.item.value;
        // Here, I have to call onAddItem twice.
        onAddItem(item);
        onAddItem(item + " second time");
        
    }

    return (
        <div>
            <form onSubmit={ handleSubmit } >
                <input value={ inputValue }  
                onChange={(e) => setInputValue(e.target.value) }  name="item"></input>
                <button type="submit">Add</button>
            </form>
        </div>
    )
}

export default ItemForm;

这是应用程序的实际行为

实际行为

这是预期的行为

预期行为

为什么会发生这种情况,我该如何解决?

标签: javascriptreactjsuse-state

解决方案


状态更新是异步的

对于您的两次调用, itemsList 数组完全相同。:

假设你有一个数组 : [1,2,3]。您的代码本质上所做[1,2,3,4]的是第一次和[1,2,3,5]第二次。

setItemList([...itemList, item]) //[1,2,3,4]
setItemList([...itemList, item]) //[1,2,3,5]

您在第二次更新中的数组仍在使用原始值。

要做到这一点,您可以使用这种使用先前状态的模式。这是使用先前状态的可靠方法。

import React, { useState } from "react";
import ItemForm from "./itemForm";

function App() {
  const [itemList, setItemList] = useState([]);

  function addItem(item) {
    setItemList(itemList => ([...itemList, item]));
  }

  return (
    <div>
      <ItemForm onAddItem={ addItem } />
      { itemList && 
          itemList.map((item, i) => <ul key={ i + itemList } >{ item }</ul>) }
    </div>
  );
}

export default App;
import React, { useState } from 'react';

function ItemForm({ onAddItem }) {
    const [inputValue, setInputValue] = useState('');

    function handleSubmit(e) {
        e.preventDefault();
        var item = e.target.item.value;
        // Here, I have to call onAddItem twice.
        onAddItem(item);
        onAddItem(item + " second time");
        
    }

    return (
        <div>
            <form onSubmit={ handleSubmit } >
                <input value={ inputValue }  
                onChange={(e) => setInputValue(e.target.value) }  name="item"></input>
                <button type="submit">Add</button>
            </form>
        </div>
    )
}

export default ItemForm;

推荐阅读