如何在React hook中使用useState数组推入元素?这是React状态中的旧方法吗?还是有什么新的方法?
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>
因为只有在click
事件(一个“离散”的事件)中对theArray
进行了更新,我可以在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>
再详细介绍一下,这里有一些常见的例子。首先是:
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
您可以在自定义状态的末尾附加数据数组:
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]);
最推荐的方法是同时使用包装函数和展开运算符。例如,如果您已经像这样初始化了一个名为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
setTheArray([...theArray, newElement]);
是最简单的答案,但要注意theArray中项目的变异。请使用数组项的深层克隆。
我尝试使用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;
});
};
setTheArray(currentArray => [...currentArray, newElement])
。在useEffect(...theArray..., [])
中,需要注意theArray
是一个常量,因此需要使用函数式更新来处理未来渲染的值。 - AprillionuseEffect
的例子...? - T.J. CrowderuseEffect
的依赖列表为空[]
,它将仅在第一次渲染时执行。因此,效果内部的theArray
值始终为initialArray
。在不适用setTheArray([...initialArray, newElement])
的情况下,并且当theArray
常量始终等于initialValue
时,则需要使用函数更新。 - AprillionforceUpdate
(在类组件中),或者 B) 更改其他状态成员(以触发重新渲染)来解决问题。但是,任何使用数组的组件都会优化,当数组不变时不会重新渲染(memo
,...)。 - T.J. Crowder