如何通过 useState 在 React Hooks 推送方法?

如何往 React hook useState 数组中添加元素? 这是 react 状态下的老方法吗?还是一些新的东西?

例如:setState 推送示例 ?

436813 次浏览

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

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

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

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

有时你可以不使用回调表单,如果你只有更新某些特定用户事件处理程序中的数组,如click(但不像mousemove):

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

React确保渲染被刷新的事件是“离散事件”。在这里上市。

实例(将回调函数传递给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事件中的更新(其中一个"离散"事件),我可以在addEntry中直接更新:

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类组件中使用“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>
);
}

进一步展开, 这里有一些常见的例子。开始:< / p >

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

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中的对象数组,但在使用打印稿时出现以下错误:

类型“TxBacklog[] | undefined”必须有一个“符号”。Iterator的方法,返回一个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]);