🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 概述 react 使用 immer 更简洁的更新复杂 state ## 安装 ``` npm install immer ``` 如果需要 use-immer ``` npm install use-immer ``` ## 示例 ### hello world ``` import produce from 'immer'; const state = { count: 0, user: { name: 'John', age: 30 } }; // 更新 state 的 count 和 user.name const newState = produce(state, draft => { draft.count = 1; draft.user.name = 'Alice'; }); console.log(state); // 原始状态未改变 console.log(newState); // 新的状态,count 为 1,user.name 为 'Alice' ``` ### 与 useState 结合 方法一: 官方 ``` const [person, setPerson] = useState({ name: 'Niki de Saint Phalle', artwork: { title: 'Blue Nana', city: 'Hamburg', image: 'https://i.imgur.com/Sd1AgUOm.jpg', } }); setPerson({ ...person, // Copy other fields artwork: { // but replace the artwork ...person.artwork, // with the same one city: 'New Delhi' // but in New Delhi! } }); ``` 方式二: 使用 produce ``` setPerson(produce(person, (draft) => { draft.artwork.city = 'New Delhi'; })); ``` 方式三: 使用 useImmer ``` const [person, updatePerson] = useImmer({ name: 'Niki de Saint Phalle', artwork: { title: 'Blue Nana', city: 'Hamburg', image: 'https://i.imgur.com/Sd1AgUOm.jpg', } }); updatePerson(draft => { draft.artwork.city = 'Lagos'; }); ``` ### Reducer 可让 reducer 更优雅 ``` import React from "react"; import { useImmerReducer } from "use-immer"; const initialState = { count: 0 }; function reducer(draft, action) { switch (action.type) { case "reset": return initialState; case "increment": return void draft.count++; case "decrement": return void draft.count--; } } function Counter() { const [state, dispatch] = useImmerReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({ type: "reset" })}>Reset</button> <button onClick={() => dispatch({ type: "increment" })}>+</button> <button onClick={() => dispatch({ type: "decrement" })}>-</button> </> ); } ```