HOWTO · React
在 React 中更新状态数组
在本文中,我们将探索状态,这是 React 的一个组成部分,因为它允许我们创建动态用户界面。
本页内容
本文想探讨 state 对象以及限制直接改变状态的根本原因。
React 中的状态是什么
React 是一个库,可让你自由地开发和设计可重用组件的样式。与 WordPress 等常见 CMS 网站或 SquareSpace 等网站构建软件相比,使用 React 构建的 Web 应用程序更快、更可定制。
React 不是一个固执己见的库,它背后的团队让 React 开发人员可以自由地按照自己的方式做事。尽管如此,该库仍然建立在某些原则之上,例如 props 的不变性和更新状态的必要程序。
一些 React 组件维护它们的状态来存储预期由于用户操作、加载的数据或其他事件而改变的数据。它是一个对象,用户可以将他们的键值对分配给这个对象。
state 最重要的特性之一是 state 值的更改会自动触发重新渲染。如果你使用可变值来呈现你的应用程序,那么 state 是存储它的理想场所。
如果你需要一个变量在 render 方法之外进行计算,你可以定义一个简单的变量或在组件实例上设置一个属性。
组件的 state 和 props 之间的最大区别在于,state 应该通过设计而改变。
要使 React Virtual DOM 功能正常工作,你必须使用内置方法来更新状态。你不能使用诸如 .push() 之类的方法来直接改变状态对象。
在 React 中使用 setState() 方法
React 组件在内部使用 setState() 方法来修改状态。React 团队强烈建议只使用 setState() 方法改变状态而不绕过它。
它有一个参数:一个应该取代现有状态的对象。React 开发人员通常必须复制现有的状态对象,对副本进行必要的更改,调用 setState() 方法,并将副本作为参数提供。
在 React 中更新数组状态值
状态属性的值类型没有限制。它可以是任何东西:字符串、数字、对象,甚至是数组。在 React 中,将数组作为状态值是很常见的。
让我们用一个实际的例子。假设你的状态值是一个包含多个对象的数组,每个对象都包含动物数据。
让我们看看如何在实践中使用那个 state 值。
import "./styles.css";
import { useState } from "react";
export default function App() {
const [animals, setAnimals] = useState([
{ type: "Lion" },
{ type: "Rabbit" },
{ type: "Wolf" }
]);
return (
<div className="App">
{animals.map((animal) => (
<h1>{animal.type}</h1>
))}
</div>
);
}
到目前为止,一切都很简单。我们使用 useState() 挂钩将 animals 状态变量的默认值设置为数组。然后我们使用 .map() 方法为每个动物渲染一个 <h1> 元素。
但是,当你需要另一只动物加入阵列时会发生什么?例如,让我们添加一个表单,用户可以在其中输入动物的类型。
一旦我们从 input 元素访问值,我们将不得不以某种方式将该值添加到 animals 状态变量,这是一个数组。
export default function App() {
const [animals, setAnimals] = useState([
{ type: "Lion" },
{ type: "Rabbit" },
{ type: "Wolf" }
]);
const handleClick = () => setAnimals([...animals, { type: "Sparrow" }]);
return (
<div className="App">
{animals.map((animal) => (
<h1>{animal.type}</h1>
))}
<button onClick={() => handleClick()}>Update the State</button>
</div>
);
}
如果你尝试直接执行 animals.push({type:"cat"}),则会导致代码出错。
相反,在这个例子中,我们添加了一个简单的按钮,当点击它时,使用扩展语法复制原始 animals 状态数组的所有值,再添加一个对象,然后更新状态。你可以在 CodeSandbox 上查看演示。
复制数组、修改数组并使用变异数组更新状态变量似乎效率低下。尽管如此,在符合 React 建议的同时,它仍然是最直接的方法。
在 React 中克隆数组或添加元素的其他方法
在上面的例子中,我们使用扩展语法来复制数组,再添加一个对象并更新状态。但是,也可以使用 .concat() 方法将特定值添加到数组中。
const newAnimalsArray = animals.concat([{ type: "Sparrow" }])
然后我们可以调用 setAnimals() 更新函数并提供 newAnimalsArray 作为参数。
同样,我们可以使用 .push() 方法将某些项目添加到数组的末尾。
或者,我们可以使用 Array 命名空间上的 .from() 方法来复制数组。让我们来看看。
const copiedArray = Array.from(animals)
copiedArray.push({type: "Sparrow"})
setAnimals(copiedArray)
React 中的类组件
类组件是过去唯一可以保持状态的类型。setState() 是更新类组件中状态的唯一有效方法。
但是,它比 useState() 钩子稍微冗长一些。
React 中的函数式组件
自从 React 16.8 版本引入钩子以来,在功能组件中维护状态成为可能。这是一个非常流行的特性,并促使 React 开发者社区更频繁地使用函数式组件。
在功能组件中,我们一起定义了两个变量。第一个变量指的是状态值本身,useState() 钩子返回的第二个值是更新函数。
假设我们有一个 number 状态变量和另一个 setNumber 函数要更新。
const [number, setNumber] = useState(0)
useState 钩子负责其余的工作。它将状态值分配给 number 变量,将更新函数分配给 setNumber 变量。