immer使用

https://immerjs.github.io/immer/zh-CN/produce

在 React 中,状态(state)是不可变的,任何状态的更新都需要生成新的状态对象。Immer 通过 produce 函数简化了这一过程,允许开发者以类似于修改可变对象的方式去更新状态,而实际上它会自动创建新的状态对象,从而保持了状态的不可变性

Produce

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

  • currentState:被操作对象的初始状态

  • draftState:currentState代理,修改的draftState不会影响currentState

  • nextState:根据 draftState 生成的最终状态

  • produce 生产 用来生成 nextState 或 producer 的函数

  • producer 生产者 通过 produce 生成,用来生产 nextState ,每次执行相同的操作

(baseState, ...arguments) => resultState

  • recipe 生产机器 用来操作 draftState 的函数

柯里化 producers

import produce from 'immer';
const toggle = produce((draft) => {
    const todo = draft.find(item => item.id === id)
    todo.done = !todo.done
})

const current = [
    {
        id:1,
        name:'你好',
        done:false
    },
    {
        id:2,
        name:'汽车',
        done:false
    },
    {
        id:2,
        name:'吃饭',
        done:false
    },
]

const nextState = toggle(current, 2)
console.log(nextState);   //id:2的done为true
console.log(current);   //id:2的done为false,不会修改原始数据

React & Immer

useState + Immer

import React, { useCallback, useState } from "react";
import {produce} from "immer";

const TodoList = () => {
  const [todos, setTodos] = useState([
    {
      id: "React",
      title: "Learn React",
      done: true
    },
    {
      id: "Immer",
      title: "Try Immer",
      done: false
    }
  ]);

  const handleToggle = useCallback((id) => {
    setTodos(
      produce((draft) => {
        const todo = draft.find((todo) => todo.id === id);
        todo.done = !todo.done;
      })
    );
  }, []);

  const handleAdd = useCallback(() => {
    setTodos(
      produce((draft) => {
        draft.push({
          id: "todo_" + Math.random(),
          title: "A new todo",
          done: false
        });
      })
    );
  }, []);

  return (<div>{*/ See CodeSandbox */}</div>)
}

useImmer 简化useState + Immer

import React, { useCallback } from "react";
import { useImmer } from "use-immer";

const TodoList = () => {
  const [todos, setTodos] = useImmer([
    {
      id: "React",
      title: "Learn React",
      done: true
    },
    {
      id: "Immer",
      title: "Try Immer",
      done: false
    }
  ]);

  const handleToggle = useCallback((id) => {
    setTodos((draft) => {
      const todo = draft.find((todo) => todo.id === id);
      todo.done = !todo.done;
    });
  }, []);

  const handleAdd = useCallback(() => {
    setTodos((draft) => {
      draft.push({
        id: "todo_" + Math.random(),
        title: "A new todo",
        done: false
      });
    });
  }, []);

useReducer + Immer

import React, {useCallback, useReducer} from "react"
import {produce} from "immer"

const TodoList = () => {
    const [todos, dispatch] = useReducer(
        produce((draft, action) => {
            switch (action.type) {
                case "toggle":
                    const todo = draft.find(todo => todo.id === action.id)
                    todo.done = !todo.done
                    break
                case "add":
                    draft.push({
                        id: action.id,
                        title: "A new todo",
                        done: false
                    })
                    break
                default:
                    break
            }
        }),
        [
            /* initial todos */
        ]
    )

    const handleToggle = useCallback(id => {
        dispatch({
            type: "toggle",
            id
        })
    }, [])

    const handleAdd = useCallback(() => {
        dispatch({
            type: "add",
            id: "todo_" + Math.random()
        })
    }, [])

    // etc
}

useImmerReducer 等于useReducer+immer

import React, { useCallback } from "react";
import { useImmerReducer } from "use-immer";

const TodoList = () => {
  const [todos, dispatch] = useImmerReducer(
    (draft, action) => {
      switch (action.type) {
        case "toggle":
          const todo = draft.find((todo) => todo.id === action.id);
          todo.done = !todo.done;
          break;
        case "add":
          draft.push({
            id: action.id,
            title: "A new todo",
            done: false
          });
          break;
        default:
          break;
      }
    },
    [ /* initial todos */ ]
  );

Redux + Immer

### 结合 Zod 和 Immer 进行 Vue 的状态管理与数据验证 在现代前端开发中,Vue 是一种流行的框架,而结合第三方库如 **Zod** 和 **Immer** 可以为应用提供更强大的功能支持。以下是关于如何集成这些工具来实现状态管理和数据验证的具体方法。 #### 使用 Immer 简化状态变更操作 Immer 提供了一种简单的方式来处理不可变的状态更新逻辑。通过 `produce` 函数,开发者可以像修改可变对象一样编写代码,但实际上它会返回一个新的副本[^4]。 下面是一个简单的例子展示如何在 Vue使用 Immer: ```javascript import produce from 'immer'; export default { data() { return { state: { users: [{ id: 1, name: "Alice", age: 25 }], }, }; }, methods: { addUser() { this.state = produce(this.state, draft => { draft.users.push({ id: 2, name: "Bob", age: 30 }); }); } } }; ``` 此代码片段展示了如何利用 Immer 来安全地更改嵌套结构中的数组或对象属性[^4]。 #### 集成 Zod 实现数据验证 Zod 是一个 TypeScript-first 的模式定义和验证库,能够帮助我们快速构建复杂的输入校验规则并自动生成类型声明文件[^5]。为了将其融入到 Vue 应用程序当中,可以通过以下方式完成配置: 1. 定义 Schema:首先需要基于业务需求设计对应的 schema; 2. 数据解析:当接收到外部传入的数据时,调用 `.parse()` 方法对其进行检验;如果不符合预期则抛出错误。 示例代码如下所示: ```typescript // schemas.ts import { z } from "zod"; const UserSchema = z.object({ id: z.number(), name: z.string().min(2), age: z.coerce.number().int().positive() }); type UserType = z.infer<typeof UserSchema>; export { UserSchema, UserType }; ``` 接着,在组件内部引入上述定义好的 Schema 并执行相应的检查流程: ```javascript <script setup lang="ts"> import { ref } from 'vue'; import { UserSchema } from './schemas'; const formData = ref<{id?: number|string|null;name:string|undefined|null;age:number|undefined|null}>({}); function handleSubmit(event:Event){ event.preventDefault(); try{ const validatedData = UserSchema.parse(formData.value); console.log('Valid Data:',validatedData); // Proceed further after successful validation. }catch(error){ alert((error as Error).message); } } </script> <template> <form @submit="handleSubmit"> <!-- Form fields here --> <button type="submit">Submit</button> </form> </template> ``` 以上就是将 Zod 融入 Vue 开发环境下的基本思路[^5]。 #### 组合运用两者提升整体体验 最后一步则是把前面提到的技术结合起来形成完整的解决方案——即每当触发某些特定事件(比如提交表单或者异步请求成功回调)之后立即同步更新本地存储的同时也重新评估当前显示的内容是否仍然满足既定条件限制。这样不仅可以保障最终呈现给用户的界面始终处于合法范围内而且还能有效减少不必要的渲染次数从而提高性能表现[^6]。 ```javascript methods:{ async fetchData(){ let rawResponse=await fetch('/api/users'); let jsonResponse= await rawResponse.json(); try{ const parsedUsers=UserArraySchema.parse(jsonResponse); this.setState(parsedUsers); } catch(err){ console.error("Invalid API response:",err.message); } }, setState(newState){ this.state=produce(this.state,(draft)=>{ draft.list=newState; }) } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值