react之useState详解

在这里插入图片描述

1. 为什么要用useState?

  • 它是React 16.8 的新特性,我们在React里面一般都是用Class去写组件,但是有时候会发现不用它更方便,但是问题来了:不用Class的时候,数据的状态改变如何存储呢?
  • 如果你用 var,let,const 等等,你会发现:值虽然改变了,但是页面并没有重新渲染,也就是说,这些关键字定义的值并不是响应式的
  • 这个时候,就轮到 useState 上场了,它允许我们定义状态变量,并且能保证在页面上能重新渲染,数据是响应式的。

2. 基本语法

const [state, setState] = useState(initialState);
  • state => 存储的状态值
  • setState => 用来修改状态的函数
  • initialState => 首次渲染的初始值
  • 比如 useState 返回一个数组,长度为 2
// 通常使用的定义方法
const [key, setKey] = useState(0);
// 但是怕大家不好理解,所以也可以拆开,如下:
const keyArr = useState(0);
const key = keyArr[0];
const setKey = keyArr[1];

3. 实践案例

const initData = [
  {
    imgSrc: '',
    contentStr: '第一条评论',
  },
  {
    imgSrc: '',
    contentStr: '第二条评论',
  },
  {
    imgSrc: '',
    contentStr: '第三条评论',
  },
];
import { useState, useEffect } from "react";
// useEffect  用于监听数据变化,不要也可以的
const BuyComment = () => {
  // 带入初始值
  const [dataList, setDataList] = useState(initData);
  // 重点在这里
  // 往数组里添加数据
  const addRule = () => {
    let obj = {
      imgSrc: [],
      contentStr: '新的评论',
    };
    // 有深拷贝的必要,防止数据出问题
    const addItems = JSON.parse(JSON.stringify(dataList));
    addItems.push(obj);
    // 在这里完成值的修改
    setDataList(addItems);
  };
   return (
	<div>
	  {dataList.map((item, i) => {
        return (
          <div className={styles.mianBorder} key={i}>
              {item.contentStr}
          </div>
        );
      })}
       <div className={styles.addDiv}>
          <span className={styles.addCom} onClick={addRule}>
            + 添加评论
          </span>
        </div>
	</div>
   )
};
// 用于监听数据变化的
useEffect(() => {
  console.log(dataList);
}, [dataList]);
export default BuyComment;
  • 做完以上的步骤,点击 添加评论 就会发现数据同步更改了。

4. useState 的惰性初始化

  • useState 初始值是支持惰性初始化的,所以我们可以传递一个函数给它。
  • 这个函数会在组件第一次渲染的时候执行,当然,后续的渲染就不会执行了。
  • 之所以有这个特性,是为了优化性能。因为有时候我们会遇到非常庞大的数据处理,可能还要进行深拷贝,这些操作还是很耗性能的,如果每次组件渲染的时候都会执行,那代价是很大的,但又不是必须的,所以 useState 的优点就体现出来了:只执行一次,大大的减少了操作的性能和代价。
// 假设这里数据量非常大:jsonObj,我们需要对它进行解析,计算等等操作
const jsonObj = "{...}"; // 可能是一个很大的js 对象 或者json字符串

function DemoComponent() {
  const [data, setData] = useState(() => {
  	console.log("执行了")
  	// 这种深拷贝是很耗性能的,所以我们在这里先把数据处理好,并且只处理一次
    return JSON.parse(JSON.stringify(jsonObj ));
  });
}
  • 上面的代码中,打印只会执行一次。
  • 避免重复的操作,提高代码性能。

1. 希望本文能对大家有所帮助,如有错误,敬请指出

2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!后续将继续奉献优质好文
4. 如果存在疑问,可以私信我(主页有Q)

在这里插入图片描述

### React 中 `useState` 的用法详解 #### 初始化状态 在 React 中,`useState` 是一种 Hook,用于在函数组件中管理状态。它接收一个参数作为状态的初始值,并返回当前状态以及更新该状态的一个函数。 以下是初始化状态的例子: ```javascript import React, { useState } from 'react'; function Example() { const [count, setCount] = useState(0); // 初始状态为 0 return ( <div> <p>计数器: {count}</p> <button onClick={() => setCount(count + 1)}>增加</button> </div> ); } ``` 在这个例子中,`useState(0)` 将 `count` 的初始值设置为 `0`[^1]。 #### 更新状态 通过调用由 `useState` 返回的第二个值(即更新函数),可以改变状态的值。每次调用此函数都会触发重新渲染。 下面展示如何更新状态: ```javascript function ColorPicker() { const [color, setColor] = useState('red'); // 初始颜色为 red function handleChange(event) { setColor(event.target.value); } return ( <div> <input type="text" value={color} onChange={handleChange} /> <h1 style={{ color }}>所选颜色:{color}</h1> </div> ); } ``` 在此示例中,当输入框中的文本发生变化时,`setColor` 函数被调用来更新 `color` 状态[^2]。 #### 使用对象作为状态 如果需要使用复杂数据结构(如对象)来存储多个属性,则需要注意 `useState` 不会对新旧状态进行浅层合并操作。因此,在更新部分字段时需手动保留其他未更改的字段。 例如: ```javascript function ProfileForm() { const [profile, setProfile] = useState({ name: '', age: '' }); function handleNameChange(e) { setProfile({ ...profile, name: e.target.value }); // 合并现有 profile 数据与新的名字 } function handleAgeChange(e) { setProfile({ ...profile, age: e.target.value }); } return ( <form> <label>Name:</label><br/> <input type="text" value={profile.name} onChange={handleNameChange}/> <label>Age:</label><br/> <input type="number" value={profile.age} onChange={handleAgeChange}/> <pre>{JSON.stringify(profile)}</pre> </form> ); } ``` 在这里展示了如何利用扩展运算符 `{...profile}` 来保持原有状态不变的同时仅修改特定键值[^1]。 #### 常见问题及解决方案 1. **异步更新**: 调用 setState 并不立即执行更新动作;相反,React 可能会批量处理这些请求以提高性能。如果你依赖前一状态计算下一状态,请传入回调形式而非直接读取变量。 解决方案如下所示: ```javascript function Counter() { const [counter, setCounter] = useState(0); function incrementTwice() { setCounter(prevState => prevState + 1); // 正确做法 setCounter(prevState => prevState + 1); } return ( <> Count: {counter} <button onClick={incrementTwice}>Increment Twice</button> </> ) } ``` 2. **条件渲染引发错误**: 如果尝试基于尚未定义的状态来进行逻辑判断可能会抛出异常。始终确保先验证是否存在再访问其成员。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧阳呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值