useImmer的使用以及与useState的对比

前言

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>
	)
}

你可能感兴趣的:(react,javascript,react.js,前端,ecmascript)