【React】useImmer的使用以及与useState的对比

本文介绍了immer,一个用于处理不可变状态的第三方模块,通过ES6的proxy实现。文章对比了immer与React内置的useState在处理数组和对象状态更新时的差异,展示了immer如何简化操作过程。
摘要由CSDN通过智能技术生成

前言

immer是一个第三方模块,可以更加方便的处理不可变状态,其核心实现是利用ES6的proxy。

下载

npm

npm install immer use-immer

yarn

yarn add immer use-immer

immer基本使用

语法:

produce(currentState, recipe: (draftState) => void | draftState, ?PatchListener): nextState

  • currentState: 被操作对象的最初状态
  • draftState: 根据 currentState 生成的草稿状态,它是currentState的代理,对draftState 所做的任何修改都将被记录并用于生成 nextState。在此过程中,currentState 将不受影响
  • nextState:根据draftState 生成的最终状态
  • produce: 用来生成 nextState 或 producer 的函数
  • producer: 生产者 通过 produce 生成,用来生产nextState ,每次执行相同的操作
  • recipe: 生产机器 用来操作draftState 的函数
  • PatchListener可有可无的

与useState对比

处理数组

需求:点击按钮添加一行数据

useState实现

import { useState } from "react"

function App() {
	const [list, setList] = useState([
    { id: 1, text: "aaa" },
    { id: 2, text: "bbb" },
    { id: 3, text: "ccc" },
  ])
  const handleClick = () => {
    setList([...list,{ id: 4, text: "ddd" }])
  }
  return (
  <div>
    <button onClick={handleClick}>点击添加</button>
    <ul>
        {list.map((item) => {
          return <li key={item.id}>{item.text}</li>
        })}
    </ul>
  </div>
	)
}

useImmer实现

import { useImmer } from "use-immer"

function App() {
	const [list, setList] = useImmer([
    { id: 1, text: "aaa" },
    { id: 2, text: "bbb" },
    { id: 3, text: "ccc" },
  ])
  const handleClick = () => {
    setList((draft) => {
      draft.push({ id: 4, text: "ddd" })
    })
  }
  return (
  <div>
    <button onClick={handleClick}>点击添加</button>
    <ul>
        {list.map((item) => {
          return <li key={item.id}>{item.text}</li>
        })}
    </ul>
  </div>
	)
}

处理对象

需求:点击将"小明" 变成 “大明”

useState实现

import { useState } from "react"
import { cloneDeep } from "lodash"

function App() {
	const [userInfo, setUserInfo] = useState(
  	{ 
      name:{
        firstname:"小",
        lastname:"明"
      },
      age:23
    }
  )
  const handleClick = () => {
    // 方法一:
    setUserInfo({ 
      ...userInfo,
      name:{
        ...userInfo.name,
        firstname:"大"
      }
    })
    // 方法二:也可以使用lodash
    const cloneUserInfo = cloneDeep(userInfo)
    cloneUserInfo.name.firstname = "大"
    setUserInfo(cloneUserInfo)
  }
  return (
    <div>
      <button onClick={handleClick}>修改name</button>
      <div>{ JSON.stringify(userInfo) }</div>
    </div>
	)
}

useImmer实现

import { useImmer } from "use-immer"

function App() {
	const [userInfo, setUserInfo] = useImmer(
  	{ 
      name:{
        firstname:"小",
        lastname:"明"
      },
      age:23
    }
  )
  const handleClick = () => {
    setUserInfo((draft) => {
      draft.name.firstname = "大"
    })
  }
  return (
    <div>
      <button onClick={handleClick}>修改name</button>
      <div>{ JSON.stringify(userInfo) }</div>
    </div>
	)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

田本初

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

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

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

打赏作者

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

抵扣说明:

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

余额充值