React Hooks(useState)中的Push方法?


Answers:


310

使用时useState,您可以获取状态项的更新方法:

const [theArray, setTheArray] = useState(initialArray);

然后,当您要添加新元素时,可以使用该函数并传入新数组或将创建新数组的函数。通常情况下是后者,因为状态更新是异步的,有时是分批的:

setTheArray(oldArray => [...oldArray, newElement]);

有时,如果您针对某些特定的用户事件click(例如,但不喜欢mousemove)更新处理程序中的数组,则无需使用回调形式就可以摆脱困境:

setTheArray([...theArray, newElement]);

React保证刷新渲染的事件是此处列出的“离散事件” 。

实时示例(将回调传递给setTheArray):

因为其中的唯一更新theArrayclick事件中的一个(“离散”事件之一),所以我可以通过直接更新来解决addEntry


1
...并尝试setTheArray(currentArray => [...currentArray, newElement])上述方法不起作用。最有可能的useEffect(...theArray..., []),它认识到这一点很重要theArray是恒定的,所以功能的更新,需要从未来的价值渲染
Aprillion

@Aprillion-不太确定您在该useEffect示例中说的是什么...?
TJ Crowder

1
如果的useEffect依赖项列表为空[],则它将仅在第一个渲染期间执行。因此,theArray内部效果的值将始终为initialArray。在setTheArray([...initialArray, newElement])没有意义的情况下,并且当theArray常数始终等于时initialValue,则需要功能更新。
4

@Aprillion-恐怕我还是没有得到它,可能有点密集。:-)为什么只需要初始数组值就需要效果?(我的意思是,可能用例很少,但是...)即使您这样做,它与问题有什么关系?
TJ Crowder

1
伙计,我为此挣扎了最长的时间。我以为setTheArray(()=>theArray.concat(newElement))可以,但是不可以!回调的参数使所有差异。
杰夫·洛里

51

为了进一步扩展,下面是一些常见示例。从...开始:

const [theArray, setTheArray] = useState(initialArray);
const [theObject, setTheObject] = useState(initialObject);

在数组末尾推送元素

setTheArray(prevArray => [...prevArray, newValue])

在对象末尾推送/更新元素

setTheObject(prevState => ({ ...prevState, currentOrNewKey: newValue}));

在对象数组末尾推送/更新元素

setTheArray(prevState => [...prevState, {currentOrNewKey: newValue}]);

将元素推入数组对象的末尾

let specificArrayInObject = theObject.array.slice();
specificArrayInObject.push(newValue);
const newObj = { ...theObject, [event.target.name]: specificArrayInObject };
theObject(newObj);

这也是一些工作示例。 https://codesandbox.io/s/reacthooks-push-r991u


5
感谢您提供的所有示例。我遇到的确切问题是数组对象末尾的Push元素。我尝试了许多不同的事情,但无法将它们拼凑在一起。
双打

1
使用prevState解决了我的问题,即仅最后一次调用被应用在同时数组concat和filter上。
Henrique Bruno

5

在React类组件中以“正常”状态进行操作的方式相同。

例:

function App() {
  const [state, setState] = useState([]);

  return (
    <div>
      <p>You clicked {state.join(" and ")}</p>
      //destructuring
      <button onClick={() => setState([...state, "again"])}>Click me</button>
      //old way
      <button onClick={() => setState(state.concat("again"))}>Click me</button>
    </div>
  );
}

这将与onClick一起使用,但是setState(oldState => [... oldState,pushsomething])是您应该如何操作
Cyrus

3
// Save search term state to React Hooks with spread operator and wrapper function

// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query))

// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query))

// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query])

// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query])

https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc



1

推荐的方法是一起使用包装函数和散布运算符。例如,如果您初始化了这样的状态name

const [names, setNames] = useState([])

您可以像这样推送到该数组,

setNames(names => [...names, newName])

希望能有所帮助。


请不要发布仅链接的答案。该链接将来可能会断开。而是创建该文章的文章,并确保实际回答该问题。
BlackCetha

尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。-评分
ilke444

1

您可以在自定义状态的末尾追加数据数组:

  const [vehicleData, setVehicleData] = React.useState<any[]>([]);
  setVehicleData(old => [...old, ...newArrayData]);

例如,在下面,您将显示axios的示例:

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        {
          url: `http://localhost:4000/api/vehicle?page=${page + 1}&pageSize=10`,
          method: 'get',
        }
      );
      setVehicleData(old => [...old, ...result.data.data]);
    };

    fetchData();
  }, [page]);

0

我尝试了上述方法将对象推入useState中的对象数组,但使用TypeScript时出现以下错误:

输入'TxBacklog [] | 未定义”必须具有返回iterator.ts(2488)的“ Symbol.iterator”方法

tsconfig.json的设置显然是正确的:

{
   "compilerOptions": {
   "target": "es6",
   "lib": [
      "dom",
      "dom.iterable",
      "esnext",
      "es6",
],

该解决方法解决了该问题(我的示例代码):

接口:

   interface TxBacklog {
      status: string,
      txHash: string,
   }

状态变量:

    const [txBacklog, setTxBacklog] = React.useState<TxBacklog[]>();

将新对象推入数组:

    // Define new object to be added
    const newTx = {
       txHash: '0x368eb7269eb88ba86..',
       status: 'pending'
    };
    // Push new object into array
    (txBacklog) 
       ? setTxBacklog(prevState => [ ...prevState!, newTx ])
       : setTxBacklog([newTx]);

0

如果要推送特定索引,可以执行以下操作:

   const handleAddAfterIndex = index => {
       setTheArray(oldItems => {
            const copyItems = [...oldItems];
            const finalItems = [];
            for (let i = 0; i < copyItems.length; i += 1) {
                if (i === index) {
                    finalItems.push(copyItems[i]);
                    finalItems.push(newItem);
                } else {
                    finalItems.push(copyItems[i]);
                }
            }
            return finalItems;
        });
    };
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.