网站建设与网页设计教程,网站建设专员一定要会网站建设吗,阿里云 网站部署,企业商务网站设计与开发文章目录 一、useState1. 更新基本类型数据2. 更新对象3. 更新嵌套对象4. 更新数组5.更新数组对象 二、Immer1. 什么是Immer2. 使用use-immer更新嵌套对象3. 使用useImmer更新数组内部的对象 一、useState
react中文官网教程
1. 更新基本类型数据
在函数式组件中#xff0c… 文章目录 一、useState1. 更新基本类型数据2. 更新对象3. 更新嵌套对象4. 更新数组5.更新数组对象 二、Immer1. 什么是Immer2. 使用use-immer更新嵌套对象3. 使用useImmer更新数组内部的对象 一、useState
react中文官网教程
1. 更新基本类型数据
在函数式组件中可以使用 useState 这个 Hook 来定义和管理组件的状态。useState 接受一个初始状态作为参数并返回一个包含 state 和更新 state 的方法的数组。
下面是一个例子展示了如何在函数式组件中定义自己的 state:
import React, { useState } from react;function MyComponent() {// 定义一个名为 count 的 state 变量并将初始值设置为 0const [count, setCount] useState(0);const handleClick () {setCount(count 1);};return (divpCount: {count}/pbutton onClick{handleClick}Increase Count/button/div);
}export default MyComponent;在上面的例子中我们使用 useState 创建了一个名为 count 的状态变量并将其初始值设为 0。然后我们将 count 的值展示在 p 元素中并在按钮的点击事件中调用 setCount 来更新 count 的值。
每当我们调用 setCount 来更新 count 的值时React 会重新渲染组件并传递更新后的值给 count。
2. 更新对象
在函数式组件中使用useState更新state中的对象可以通过以下步骤
导入useState
import React, { useState } from react;创建一个对象作为初始状态state
const initialState { name: John, age: 30, email: johnexample.com };在组件内部使用useState钩子声明state
const [person, setPerson] useState(initialState);这里person是状态对象setPerson是一个更新状态的函数。useState(initialState)是useState的初始值参数。
在组件中使用状态对象
return (divpName: {person.name}/ppAge: {person.age}/ppEmail: {person.email}/p/div
);使用setPerson函数来更新状态对象的值
const updateEmail () {setPerson({ ...person, email: updatedexample.com });
};这里使用了ES6的展开语法spread syntax来复制现有的person对象并更新email属性的值。
在组件中调用updateEmail函数来更新状态
button onClick{updateEmail}Update Email/button完整的示例代码如下
import React, { useState } from react;const App () {const initialState { name: John, age: 30, email: johnexample.com };const [person, setPerson] useState(initialState);const updateEmail () {setPerson({ ...person, email: updatedexample.com });};return (divpName: {person.name}/ppAge: {person.age}/ppEmail: {person.email}/pbutton onClick{updateEmail}Update Email/button/div);
};export default App;通过点击Update Email按钮可以更新email属性的值为updatedexample.com。
在React的函数式组件中使用useState来更新一个对象的state时有几个注意点需要特别注意 useState函数仅仅是按照传入的初始值来初始化state并不会合并对象。因此在更新state时需要先使用解构方式取出旧的对象属性值然后再设置新的对象属性值。 由于useState是按照值的变化来判断是否重新渲染组件的因此在更新state时需要保证每一次更新都是返回一个新的对象。直接对原对象进行修改并返回会导致state没有发生变化从而不会触发重新渲染。 可以使用展开运算符扩展现有对象再进行属性的更改。这样可以确保每次都返回一个新的对象。
为什么要注意这些点呢
首先useState是基于值的比较来判断是否重新渲染组件的如果不注意每次都返回一个新的对象可能会导致state没有发生变化从而不会触发重新渲染无法更新组件视图。
其次由于函数式组件没有实例的概念每次组件渲染都是独立的因此无法像类组件中使用this.setState那样自动合并对象属性。因此在更新state时需要手动合并旧的对象属性值和新的对象属性值以确保不丢失任何旧的state属性。
最后使用展开运算符扩展对象的方式可以确保每次都返回一个全新的对象这样可以避免直接对原对象进行修改而导致state没有发生变化的问题。
3. 更新嵌套对象
在React的函数式组件中使用useState更新state中的嵌套对象可以使用扩展运算符spread operator来实现。
举例说明假设有一个包含嵌套对象的state如下所示
const [state, setState] useState({name: John,age: 30,address: {street: 123 Main St,city: New York,state: NY}
});要更新state中的嵌套对象可以使用useState的setState函数传递一个新的对象并使用扩展运算符将原有的state进行展开再覆盖需要更新的属性。例如要更新address对象的city属性可以使用以下代码
setState({...state,address: {...state.address,city: Los Angeles}
});上面的代码首先使用扩展运算符将原有的state展开然后再针对需要更新的嵌套对象进行展开并更新特定的属性。在本例中我们更新了address对象的city属性将其值从New York更新为Los Angeles。
完整的示例代码如下所示
import React, { useState } from react;function App() {const [state, setState] useState({name: John,age: 30,address: {street: 123 Main St,city: New York,state: NY}});const updateCity () {setState({...state,address: {...state.address,city: Los Angeles}});};return (divpName: {state.name}/ppAge: {state.age}/ppStreet: {state.address.street}/ppCity: {state.address.city}/ppState: {state.address.state}/pbutton onClick{updateCity}Update City/button/div);
}export default App;在上述示例中我们首先使用useState定义了包含嵌套对象的state然后在组件中显示了state中的属性。最后我们使用一个按钮来调用updateCity函数该函数会更新state中的嵌套对象。点击按钮后更新后的city属性值将显示为Los Angeles。
4. 更新数组
在函数式组件中使用useState来更新state中的数组可以通过结构赋值的方式获取数组和更新数组的函数。一般情况下使用useState更新数组时需要注意以下几点 为了保持state的不可变性应该使用数组的展开运算符spread operator来创建一个新的数组。 当更新数组时需要将要更新的元素和其余元素区分开来。通常使用Array.map函数来遍历数组并找到要更新的元素。 可以使用Array.filter函数过滤数组中的元素从而可以删除特定的元素。 注意在更新数组时在判断相等性时使用严格相等运算符而不是用“浅比较”运算符。
下面是一个更新数组的例子
import React, { useState } from react;function Example() {const [list, setList] useState([1, 2, 3, 4, 5]);const handleUpdate () {// 通过展开运算符创建一个新的数组并更新数组的第一个元素setList([...list.slice(0, 1), 100, ...list.slice(2)]);};const handleDelete (item) {// 使用filter过滤数组删除特定的元素setList(list.filter((el) el ! item));};return (divul{list.map((item) (li key{item}{item}button onClick{() handleDelete(item)}删除/button/li))}/ulbutton onClick{handleUpdate}更新/button/div);
}export default Example;在这个例子中list是一个包含数字的数组。点击列表项后的“删除”按钮会删除相应的元素点击“更新”按钮会将数组的第一个元素更新为100。每次更新数组时使用展开运算符创建一个新的数组并把更新的元素插入到适当的位置这样可以保持state的不可变性。在删除元素时使用filter函数过滤掉特定的元素。
5.更新数组对象
在函数式组件中使用 useState 来更新 state 数组中的内部对象可以使用解构赋值的方式来获取数组中的指定对象并使用 useState 来更新该对象的属性。
首先在函数式组件中使用 useState 定义一个状态变量可以设置初始状态为一个包含内部对象的数组。例如使用以下代码定义一个状态变量 items并设置初始状态为一个包含两个内部对象的数组
const [items, setItems] useState([{ name: apple, quantity: 1 },{ name: banana, quantity: 2 }
]);然后通过解构赋值的方式获取数组中的指定对象并使用 useState 更新该对象的属性。例如通过以下代码获取数组中的第一个对象 item 并更新其 name 属性
const [item, setItem] useState(items[0]);const handleChangeName () {setItem(prevItem ({ ...prevItem, name: orange }));
};在上述代码中setItem 函数通过接收一个回调函数来更新 item 对象的属性。该回调函数使用展开运算符 ... 将之前的属性拷贝到一个新的对象中并更新 name 属性为 orange。
需要注意的是在更新数组时不能直接修改数组中的对象。要更新数组中的对象需要先拷贝数组然后再更新其中的对象。可以使用 Array.map() 方法来拷贝数组并更新其中的对象。例如使用以下代码将数组中的第一个对象的 name 属性改为 orange
const updatedItems items.map((item, index) {if (index 0) {return { ...item, name: orange };}return item;
});setItems(updatedItems);上述代码中Array.map() 方法遍历数组当索引为 0 的时候返回一个新的对象并更新其 name 属性为 orange否则返回原来的对象。然后将得到的新数组 updatedItems 设置为新的状态值。
二、Immer
1. 什么是Immer
Immer是一个JavaScript库用于管理不可变状态。它通过基于原始状态创建一个新的状态树来实现不可变性。它提供了一种简单而直观的方式来处理复杂的状态更新逻辑使代码更易于理解和维护。Immer可以与任何JavaScript框架或库一起使用并且对于处理大型数据结构和深层嵌套的对象非常有用。它是一个流行的工具用于管理JavaScript应用程序中的状态。
在React的函数式组件中推荐使用Immer来处理复杂的数据state特别是深层嵌套的数组对象有以下几个原因 操作不可变数据更加方便Immer提供了一种简洁的方式来直接对不可变数据进行修改。通过使用Immer的produce函数可以在不直接修改原始数据的情况下创建一个可变的草稿副本并且在草稿上进行所有的更改操作。这样可以避免因为直接修改原始数据而导致的引用问题和副作用问题。 性能优化Immer采用了一种优化技术称为“结构共享”它能够在不实际复制数据的情况下实现不可变数据的修改。这种技术可以大大提高性能特别是对于大型、深层嵌套的数据结构。 减少模板嵌套深度在处理深层嵌套的数组对象时使用Immer可以减少模板嵌套的深度。因为Immer提供了一种更简洁、更直观的方式来修改深层嵌套的数据这能够提高代码的可读性和可维护性。
总之使用Immer可以帮助我们更方便地处理复杂的数据state尤其是深层嵌套的数组对象。它简化了对不可变数据的操作并提供了性能优化的机制使得我们能够更加高效地开发React应用。
2. 使用use-immer更新嵌套对象
在React的函数式组件中可以使用use-immer库来更新嵌套对象的state。use-immer是基于Immer库的React Hook封装它可以方便地进行不可变状态更新。
以下是一个示例展示如何使用use-immer更新嵌套对象的state
首先安装use-immer库
npm install use-immer然后导入useImmer函数并在函数式组件中使用它
import React, { useState } from react;
import { useImmer } from use-immer;function App() {const [state, setState] useImmer({user: {name: John,age: 25}});// 更新嵌套对象的示例函数const updateUserName () {setState(draft {draft.user.name Tom;});};return (divh1{state.user.name}/h1p{state.user.age}/pbutton onClick{updateUserName}Update Name/button/div);
}export default App;在上面的示例中我们使用useState和useImmer来声明和初始化state。state是一个嵌套对象包含一个user对象。然后我们在updateUserName函数中使用setState函数来更新嵌套对象的state。在setState的回调函数中我们可以使用draft参数来修改状态。
使用use-immer库的好处是我们可以在回调函数中直接修改draft对象就像在原始状态上进行修改一样。useImmer会负责处理不可变性最终生成一个新的状态并将其应用于组件。
以上是使用use-immer库在React的函数式组件中更新嵌套对象状态的示例。可以根据实际需求进行相应的修改和扩展。
3. 使用useImmer更新数组内部的对象
可以使用useImmer hook结合immer来更新函数式组件中数组内部的对象。useImmer hook是在React中使用Immer库的推荐方式。
以下是一个示例说明如何使用useImmer更新数组内部的对象
import React, { useState } from react;
import { useImmer } from use-immer;const MyComponent () {// 使用useState hook创建数组状态const [data, setData] useState([{ id: 1, name: John },{ id: 2, name: Jane },{ id: 3, name: Bob },]);// 使用useImmer hook创建可变的数据副本draft和更新函数setDraftconst [draft, setDraft] useImmer(data);// 更新对象的名称const updateName (id, name) {setDraft(draft {// 使用immer的produce函数来更新draftconst item draft.find(item item.id id);if (item) {item.name name;}});};return (div{draft.map(item (div key{item.id}span{item.name}/span{/* 在组件中触发更新名称的函数 */}button onClick{() updateName(item.id, Updated Name)}Update Name/button/div))}/div);
};export default MyComponent;在上面的代码中我们首先使用useState hook创建了一个数组状态data然后使用useImmer hook创建了一个可变的数据副本draft和一个更新函数setDraft。在更新函数中我们使用immer的produce函数来更新draft修改特定ID对应的对象的名称。
在组件的返回值中我们使用draft.map循环遍历数组内部的对象显示每个对象的名称并使用按钮来触发更新的函数。
当你点击Update Name按钮时会更新draft中特定ID对应的对象的名称由于draft是可变的所以React会自动更新组件的渲染。