React Hooks 中的 Push 方法(useState)?

Push method in React Hooks (useState)?

如何将元素推送到 useState 数组 React hook 中? 这是反应状态下的旧方法吗?或者新的东西?

例如 ?

当你使用useState时,你可以得到状态项的更新方法:

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

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

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

有时,如果您 为某些特定的用户事件更新处理程序中的数组,例如 click(但不像 mousemove):

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

React 确保刷新渲染的事件是列出的“离散事件”here

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

const {useState, useCallback} = React;
function Example() {
    const [theArray, setTheArray] = useState([]);
    const addEntryClick = () => {
        setTheArray(oldArray => [...oldArray, `Entry ${oldArray.length}`]);
    };
    return [
        <input type="button" onClick={addEntryClick} value="Add" />,
        <div>{theArray.map(entry =>
          <div>{entry}</div>
        )}
        </div>
    ];
}

ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>

因为 theArray 的唯一更新是 click 事件(“离散”事件之一)中的更新,所以我可以在 [=23] 中直接更新=]:

const {useState, useCallback} = React;
function Example() {
    const [theArray, setTheArray] = useState([]);
    const addEntryClick = () => {
        setTheArray([...theArray, `Entry ${theArray.length}`]);
    };
    return [
        <input type="button" onClick={addEntryClick} value="Add" />,
        <div>{theArray.map(entry =>
          <div>{entry}</div>
        )}
        </div>
    ];
}

ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>

与在 React class 组件中使用 "normal" 状态的方式相同。

示例:

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>
  );
}

再扩展一点, 这里有一些常见的例子。开始于:

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

将元素压入数组末尾

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

Push/update 对象末尾的元素

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

Push/update 对象数组末尾的元素

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

setTheArray([...theArray, newElement]); 是最简单的答案,但要注意 theArray 中项目的突变。使用数组项的深度克隆。

最推荐的方法是同时使用包装函数和扩展运算符。例如,如果你像这样初始化了一个名为 name 的状态,

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

你可以像这样推送到这个数组,

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

希望对您有所帮助。

// 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

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

Type 'TxBacklog[] | undefined' must have a 'Symbol.iterator' method that returns an iterator.ts(2488)

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]);

如果你想在特定索引之后推送,你可以执行以下操作:

   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;
        });
    };

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

  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]);

使用 useState() 创建数组状态 首先,让我们看看如何使用 useState() 钩子来创建数组状态变量。

import React from "react";

const { useState } = React;

const [myArray, setMyArray] = useState([]);

但是,对于 React,我们需要使用 useState 返回的方法来更新数组。

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

know more