跳到主要内容

语法

2024年03月11日
柏拉文
越努力,越幸运

一、Js & Immer


1.1 produce

produce 需要一个 baseState,以及一个可用于对传入的 draft 进行所有所需更改的 recipe。关于 Immer 的有趣之处在于 baseState 将保持不变,但 nextState 将反映对 DraftState 所做的所有更改.

语法

produce(baseState, recipe: (draftState) => void): nextState
  • baseState: 传递给 produce 的不可变状态

  • recipe: 一个可用于对传入的 draft 进行所有所需更改的 recipe。在 recipe 中,所有标准的 JavaScript API 都可以在 draft 对象上使用,包括属性字段分配、删除操作和修改数组、MapSet 操作,如 pushpopsplicesetsortremove 等。

用法

  • 对象

    const obj = {
    a: 1,
    b: {
    c: {
    e: 2
    }
    }
    }
    const objNew = produce(obj, draft => {
    draft.b.c.e = 3;
    })
    console.log(obj)
    console.log(objNew);
  • 数组

    const obj = [1,2,3]
    const objNew = produce(obj, draft => {
    draft[0] = 3;
    })
    console.log(obj)
    console.log(objNew);

1.2 producers

将函数作为第一个参数传递给 produce 会创建一个函数,该函数尚未将 produce 应用于特定 state,而是创建一个函数,该函数将应用于将来传递给它的任何 state。这通常称为柯里化

语法

const baseState = xxx;

function getBaseStateNew (baseState, key,value){
return product(baseState,(draft)=>
xxxx;
);
}

const baseStateNew = getBaseStateNew(baseState,xx,xx);

用法

  • 对象

  • 数组

    const obj = [1,2,3]

    function getObjNew(baseState,index,value){
    return produce(baseState, (draft)=>{
    draft[index] = value;
    });
    }
    const objNew = getObjNew(obj,2,4);
    console.log(obj)
    console.log(objNew);

一、 Vue & Immer


1.1 useImmer

<template>
<div>
<input
type="text"
:value="obj.b.c.d"
@change="($event) => handleChange($event)"
/>
</div>
</template>

<script setup lang="ts">
import { useImmer } from "./combinatorial/useImmer";

const [obj, setObj] = useImmer({
a: "",
b: {
c: {
d: "",
},
},
});

const handleChange = (event: any) => {
const {
target: { value },
} = event;
setObj((draft: any) => {
console.log(draft)
draft.b.c.d = value;
});
console.log(obj.value.b.c.d)
};
</script>

1.2 shallowRef + immer

<template>
<div>
<input type="text" :value="obj.b.c.d" @change="($event)=> handleChange($event)">
</div>
</template>


<script setup lang="ts">
import { produce } from 'immer';
import { shallowRef } from 'vue';

const obj = shallowRef({
a: "",
b: {
c: {
d: "",
},
},
})

const handleChange = (event: any)=>{
const { target: { value} } = event;
const objNew = produce(obj.value,(draft)=>{
draft.b.c.d = value;
});
obj.value = objNew;
console.log(event)
console.log(obj.value.b.c.d)
}
</script>

二、React & Immer


2.1 useImmer

import { useImmer } from "./hooks/useImmer";

function App() {
const [form, setForm] = useImmer({
a: "",
b: {
c: {
d: "",
},
},
});

const handleInputChange = (e: any) => {
const { value } = e.target;
setForm((draft)=>{
draft.b.c.d = value;
});
};

return (
<div>
<input value={form.b.c.d} onChange={handleInputChange}></input>
</div>
);
}

export default App;

2.2 useState + immer

import { useState } from 'react';
import { produce } from "immer";

function App() {
const [form,setForm] = useState({
a: "",
b: {
c: {
d: ""
}
}
})

const handleInputChange = (e: any)=>{
const { value } = e.target;
const formNew = produce(form,(draft)=>{
draft.b.c.d = value;
});
setForm(formNew);
}

return (
<div>
<input value={form.b.c.d} onChange={handleInputChange}></input>
</div>
)
}

export default App

2.3 userImmerReducer

import { useImmerReducer,ImmerReducer } from "./hooks/useImmerReducer";

const initialState = {
a: "",
b: {
c: {
d: "",
},
},
}



const reducer:ImmerReducer<any,any> = (draft, action) => {
switch (action.type) {
case "change":
draft.b.c.d = action.value;
break;
default:
break;
}
}

function App() {
const [form, dispatch] = useImmerReducer(reducer, initialState);

const handleInputChange = (e: any) => {
const { value } = e.target;
dispatch({
type: "change",
value,
});
};

return (
<div>
<input value={form.b.c.d} onChange={handleInputChange}></input>
</div>
);
}

export default App;

2.4 useReducer + immer

import { produce } from "immer";
import { useReducer } from "react";

const initialState = {
a: "",
b: {
c: {
d: ""
}
}
}

const reducer = produce((draft,action)=>{
switch(action.type){
case "change":
draft.b.c.d = action.value;
break;
default:
break;
}
})

function App() {
const [ form,dispatch ] = useReducer(reducer,initialState);

const handleInputChange = (e: any) => {
const { value } = e.target;
dispatch({
type: "change",
value
});
};

return (
<div>
<input value={form.b.c.d} onChange={handleInputChange}></input>
</div>
);
}

export default App;