import { useCallback, useState } from 'react'; const getType = (value) => { const type = Object.prototype.toString.call(value); if (type === '[object Object]') { return 'isObject' } else if (type === '[object Array]') { return 'isArray' } return typeof value; } const useMerge = (initialState) => { const [state, setState] = useState(initialState); const stateType = getType(initialState); const handleMerge = useCallback((handleObject = {}) => { const { id, type, value } = handleObject; const merge = (state) => { let mergeData = {}; if (stateType === 'isObject') { mergeData = { ...state, ...value } } if (stateType === 'isArray') { if (type === 'remove') { mergeData = state.filter((item) => { return item.id !== id }) } if (type === 'add') { mergeData = [...state, value]; } if (type === 'update') { mergeData = state.map((item) => { if (item.id === id) { return { ...item, ...value } } return item; }) } } return mergeData; } setState((prevState) => merge(prevState)) }, []) return [state, handleMerge]; } export default useMerge;
1 cutemurphy2888 OP const [list, setList] = useMerge([{ id: 1, text: 'aa' }, { id: 2, text: 'bb' }]); const changeTT = () => { setList({ type: 'update', id: 2, value: { text: 'dxx' } }) } |
2 nulIptr 2022-11-20 22:07:27 +08:00 没注释不知道干啥用的,没 type 懒得看 merge 函数可以拿到外面 |
3 cnhongwei 2022-11-20 22:55:35 +08:00 直接用 展开运算符或 filter + 展开运行 不就行了。 |
![]() | 4 kid740246048 2022-11-20 23:01:28 +08:00 state 类的自定义 hook ,返回的 set 方法最好支持传入函数,参考 react 的这个类型 type SetStateAction<S> = S | ((prevState: S) => S); 一些场景下使用时可以避免把 state 本身加到依赖数组 |
5 nbhaohao 2022-11-21 09:00:20 +08:00 个人感觉这种需求没有不要单独一个 hook, handleMerge 是一个 util 方法, 其他地方如果需要这种 merge 的操作, 自行调用 merge 即可. ``` const [list, setList] = useState([{ id: 1, text: 'aa' }, { id: 2, text: 'bb' }]); const changeTT = () => { setList(merge(, list{ type: 'update', id: 2, value: { tex: 'dxx' } })) } ``` |
![]() | 7 4BVL25L90W260T9U 2022-11-21 09:27:17 +08:00 为啥不用 ts |
8 cutemurphy2888 OP @ospider 只有 50%的人在用 |
![]() | 9 lisongeee 2022-11-21 10:03:07 +08:00 看例子感觉不如<https://github.com/immerjs/immer> 好用 |
10 cutemurphy2888 OP @lisongeee 我看看 |
![]() | 11 xingguang 2022-11-21 15:57:07 +08:00 lodash 也有 merge 相关的库吧,没有必要重复造轮子,如果想要 render 的话就封装一个,用 useState 触发下 render |
12 hb751968840 2022-11-21 17:31:52 +08:00 ts 还是有必要的,参考一下三年前写的 https://github.com/H-jx/use-model , 支持 immer.js 、immutable ,ts 自动推导 |