在 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
变量。
Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.
LinkedIn