react中的useState和useImmer的用法

这篇具有很好参考价值的文章主要介绍了react中的useState和useImmer的用法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、useState

react中文官网教程

1. 更新基本类型数据

在函数式组件中,可以使用 useState 这个 Hook 来定义和管理组件的状态。useState 接受一个初始状态作为参数,并返回一个包含 state 和更新 state 的方法的数组。

下面是一个例子,展示了如何在函数式组件中定义自己的 state:

import React, { useState } from "react";

function MyComponent() {
  // 定义一个名为 count 的 state 变量,并将初始值设置为 0
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increase Count</button>
    </div>
  );
}

export default MyComponent;

在上面的例子中,我们使用 useState 创建了一个名为 count 的状态变量,并将其初始值设为 0。然后,我们将 count 的值展示在 <p> 元素中,并在按钮的点击事件中调用 setCount 来更新 count 的值。

每当我们调用 setCount 来更新 count 的值时,React 会重新渲染组件并传递更新后的值给 count

2. 更新对象

在函数式组件中使用useState更新state中的对象可以通过以下步骤:

  1. 导入useState:
import React, { useState } from 'react';
  1. 创建一个对象作为初始状态(state):
const initialState = { name: 'John', age: 30, email: 'john@example.com' };
  1. 在组件内部使用useState钩子声明state:
const [person, setPerson] = useState(initialState);

这里person是状态对象,setPerson是一个更新状态的函数。useState(initialState)是useState的初始值参数。

  1. 在组件中使用状态对象:
return (
  <div>
    <p>Name: {person.name}</p>
    <p>Age: {person.age}</p>
    <p>Email: {person.email}</p>
  </div>
);
  1. 使用setPerson函数来更新状态对象的值:
const updateEmail = () => {
  setPerson({ ...person, email: 'updated@example.com' });
};

这里使用了ES6的展开语法(spread syntax)来复制现有的person对象,并更新email属性的值。

  1. 在组件中调用updateEmail函数来更新状态:
<button onClick={updateEmail}>Update Email</button>

完整的示例代码如下:

import React, { useState } from 'react';

const App = () => {
  const initialState = { name: 'John', age: 30, email: 'john@example.com' };

  const [person, setPerson] = useState(initialState);

  const updateEmail = () => {
    setPerson({ ...person, email: 'updated@example.com' });
  };

  return (
    <div>
      <p>Name: {person.name}</p>
      <p>Age: {person.age}</p>
      <p>Email: {person.email}</p>
      <button onClick={updateEmail}>Update Email</button>
    </div>
  );
};

export default App;

通过点击"Update Email"按钮,可以更新email属性的值为"updated@example.com"。

在React的函数式组件中使用useState来更新一个对象的state时,有几个注意点需要特别注意

  1. useState函数仅仅是按照传入的初始值来初始化state,并不会合并对象。因此,在更新state时,需要先使用解构方式取出旧的对象属性值,然后再设置新的对象属性值。

  2. 由于useState是按照值的变化来判断是否重新渲染组件的,因此在更新state时,需要保证每一次更新都是返回一个新的对象。直接对原对象进行修改并返回会导致state没有发生变化,从而不会触发重新渲染。

  3. 可以使用展开运算符扩展现有对象,再进行属性的更改。这样可以确保每次都返回一个新的对象。

为什么要注意这些点呢?

首先,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 (
    <div>
      <p>Name: {state.name}</p>
      <p>Age: {state.age}</p>
      <p>Street: {state.address.street}</p>
      <p>City: {state.address.city}</p>
      <p>State: {state.address.state}</p>
      <button onClick={updateCity}>Update City</button>
    </div>
  );
}

export default App;

在上述示例中,我们首先使用useState定义了包含嵌套对象的state,然后在组件中显示了state中的属性。最后,我们使用一个按钮来调用updateCity函数,该函数会更新state中的嵌套对象。点击按钮后,更新后的city属性值将显示为"Los Angeles"。

4. 更新数组

在函数式组件中使用useState来更新state中的数组,可以通过结构赋值的方式获取数组和更新数组的函数。一般情况下,使用useState更新数组时需要注意以下几点:

  1. 为了保持state的不可变性,应该使用数组的展开运算符(spread operator)来创建一个新的数组。

  2. 当更新数组时,需要将要更新的元素和其余元素区分开来。通常使用Array.map函数来遍历数组,并找到要更新的元素。

  3. 可以使用Array.filter函数过滤数组中的元素,从而可以删除特定的元素。

  4. 注意在更新数组时,在判断相等性时使用严格相等运算符(===),而不是用“浅比较”运算符(==)
    react中的useState和useImmer的用法,react从入门到精通,react.js,javascript,前端

下面是一个更新数组的例子:

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 (
    <div>
      <ul>
        {list.map((item) => (
          <li key={item}>
            {item}
            <button onClick={() => handleDelete(item)}>删除</button>
          </li>
        ))}
      </ul>
      <button 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,特别是深层嵌套的数组对象,有以下几个原因:

  1. 操作不可变数据更加方便:Immer提供了一种简洁的方式来直接对不可变数据进行修改。通过使用Immer的produce函数,可以在不直接修改原始数据的情况下,创建一个可变的草稿副本,并且在草稿上进行所有的更改操作。这样可以避免因为直接修改原始数据而导致的引用问题和副作用问题。

  2. 性能优化:Immer采用了一种优化技术,称为“结构共享”,它能够在不实际复制数据的情况下实现不可变数据的修改。这种技术可以大大提高性能,特别是对于大型、深层嵌套的数据结构。

  3. 减少模板嵌套深度:在处理深层嵌套的数组对象时,使用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 (
    <div>
      <h1>{state.user.name}</h1>
      <p>{state.user.age}</p>
      <button 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和更新函数setDraft
  const [draft, setDraft] = useImmer(data);

  // 更新对象的名称
  const updateName = (id, name) => {
    setDraft(draft => {
      // 使用immer的produce函数来更新draft
      const 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会自动更新组件的渲染。文章来源地址https://www.toymoban.com/news/detail-724679.html

到了这里,关于react中的useState和useImmer的用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaScript从入门到精通系列第三十一篇:详解JavaScript中的字符串和正则表达式相关的方法

      文章目录 知识回顾 1:概念回顾 2:正则表达式字面量 一:字符串中正则表达式方法 1:split 2:search 3:match 4:replace         正则表达式用于定义一些字符串的规则,计算机可以根据正则表达式检查一个字符串是否符合规则,或者将字符串中符合规则的内容提取出来。

    2024年01月17日
    浏览(58)
  • JavaScript /react 中new Map的用法

    size属性 : size属性返回Map结构的成员总数。 set(key, value) : set方法设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。 get(key) get方法读取key对应的键值,如果找不到key,返回undefined。 has(key) has方法返回一个布尔值,表示某个键

    2024年03月15日
    浏览(55)
  • react之useState详解

    它是React 16.8 的新特性,我们在React里面一般都是用Class去写组件,但是有时候会发现不用它更方便,但是问题来了: 不用Class的时候,数据的状态改变如何存储呢? 如果你用 var,let,const 等等,你会发现:值虽然改变了,但是页面并没有重新渲染,也就是说, 这些定

    2024年04月25日
    浏览(35)
  • react 之 useState

    参考:https://blog.csdn.net/Ljwen_/article/details/125319191 一、基本使用 useState是 react 提供的一个定义响应式变量的 hook 函数,基本语法如下: 它返回一个状态和一个修改状态的方法,状态需要通过这个方法来进行修改; initialCount 是我们传入的一个初始状态,它是惰性的,我们可以

    2023年04月23日
    浏览(37)
  • React -- useState使用方法

    userState 是一个React Hook (函数)。它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果 1. useState是一个函数,返回值是一个数组 2. 数组中第一个参数是状态变量,第二个参数是set开头的函数名,用于修改变量 3. useState的参数作为count的初始值 4.使用举例

    2024年02月19日
    浏览(35)
  • 【react从入门到精通】React JSX详解

    ✍创作者:全栈弄潮儿 🏡 个人主页: 全栈弄潮儿的个人主页 🏙️ 个人社区,欢迎你的加入:全栈弄潮儿的个人社区 📙 专栏地址:react从入门到精通 【分享几个国内免费可用的ChatGPT镜像】 【10几个类ChatGPT国内AI大模型】 【用《文心一言》1分钟写一篇博客简直yyds】 【用

    2024年02月05日
    浏览(51)
  • 【react从入门到精通】深入理解React生命周期

    ✍创作者:全栈弄潮儿 🏡 个人主页: 全栈弄潮儿的个人主页 🏙️ 个人社区,欢迎你的加入:全栈弄潮儿的个人社区 📙 专栏地址:react从入门到精通 【分享几个国内免费可用的ChatGPT镜像】 【10几个类ChatGPT国内AI大模型】 【用《文心一言》1分钟写一篇博客简直yyds】 【用

    2024年02月03日
    浏览(49)
  • [react] useState的一些小细节

    因为setState修改是异步的,加上会触发函数重新渲染, 如果代码长这样  一秒再修改,然后重新触发setTImeout, 然后再触发,重复触发循环 如果这样呢 还是会,因为你执行又会重新渲染  为什么修改多次还是跟不上呢? 因为是异步修改 ,所以会出现问题,怎么办?用传函数的形式解决 C

    2024年04月13日
    浏览(41)
  • React源码解析18(6)------ 实现useState

    在上一篇文章中,我们已经实现了函数组件。同时可以正常通过render进行渲染。 而通过之前的文章,beginWork和completeWork也已经有了基本的架子。现在我们可以去实现useState了。 实现之前,我们要先修改一下我们的index.js文件: 由于我们这一篇并不会实现React的事件机制,所以

    2024年02月13日
    浏览(35)
  • React Hooks的useState、useRef使用

    React Hooks 是 React 16.8 版本引入的新特性,它允许你在不编写 class 的情况下使用 state 和其他 React 特性。其中, useState  和  useRef  是两个常用的 Hooks。 1. useState useState  是一个允许你在函数组件中添加 state 的 Hook。 使用说明: useState  返回一个状态变量和一个设置该变量的函

    2024年02月02日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包