一个帮助合并 state 的自定义 hook` 大家看看有啥问题·

2022-11-20 21:04:42 +08:00
 cutemurphy2888

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;

2240 次点击
所在节点    React
12 条回复
cutemurphy2888
2022-11-20 21:30:21 +08:00
const [list, setList] = useMerge([{ id: 1, text: 'aa' }, { id: 2, text: 'bb' }]);

const changeTT = () => {
setList({
type: 'update',
id: 2,
value: {
text: 'dxx'
}
})
}
nulIptr
2022-11-20 22:07:27 +08:00
没注释不知道干啥用的,没 type 懒得看
merge 函数可以拿到外面
cnhongwei
2022-11-20 22:55:35 +08:00
直接用 展开运算符或 filter + 展开运行 不就行了。
kid740246048
2022-11-20 23:01:28 +08:00
state 类的自定义 hook ,返回的 set 方法最好支持传入函数,参考 react 的这个类型

type SetStateAction<S> = S | ((prevState: S) => S);

一些场景下使用时可以避免把 state 本身加到依赖数组
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: {
text: 'dxx'
}
}))
}
```
nbhaohao
2022-11-21 09:01:02 +08:00
@nbhaohao
没有不要 -> 没有必要.
merge(, list -> merge(list,
ospider
2022-11-21 09:27:17 +08:00
为啥不用 ts
cutemurphy2888
2022-11-21 09:28:55 +08:00
@ospider 只有 50%的人在用·
lisongeee
2022-11-21 10:03:07 +08:00
看例子感觉不如<https://github.com/immerjs/immer> 好用
cutemurphy2888
2022-11-21 10:25:09 +08:00
@lisongeee 我看看·
xingguang
2022-11-21 15:57:07 +08:00
lodash 也有 merge 相关的库吧,没有必要重复造轮子,如果想要 render 的话就封装一个,用 useState 触发下 render
hb751968840
2022-11-21 17:31:52 +08:00
ts 还是有必要的,参考一下三年前写的 https://github.com/H-jx/use-model , 支持 immer.js 、immutable ,ts 自动推导

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/896645

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX