V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cutemurphy2888
V2EX  ›  React

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

  •  
  •   cutemurphy2888 · 2022-11-20 21:04:42 +08:00 · 2229 次点击
    这是一个创建于 731 天前的主题,其中的信息可能已经有所发展或是发生改变。
    
    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;
    
    
    12 条回复    2022-11-21 17:31:52 +08:00
    cutemurphy2888
        1
    cutemurphy2888  
    OP
       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
        2
    nulIptr  
       2022-11-20 22:07:27 +08:00
    没注释不知道干啥用的,没 type 懒得看
    merge 函数可以拿到外面
    cnhongwei
        3
    cnhongwei  
       2022-11-20 22:55:35 +08:00
    直接用 展开运算符或 filter + 展开运行 不就行了。
    kid740246048
        4
    kid740246048  
       2022-11-20 23:01:28 +08:00
    state 类的自定义 hook ,返回的 set 方法最好支持传入函数,参考 react 的这个类型

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

    一些场景下使用时可以避免把 state 本身加到依赖数组
    nbhaohao
        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: {
    text: 'dxx'
    }
    }))
    }
    ```
    nbhaohao
        6
    nbhaohao  
       2022-11-21 09:01:02 +08:00
    @nbhaohao
    没有不要 -> 没有必要.
    merge(, list -> merge(list,
    ospider
        7
    ospider  
       2022-11-21 09:27:17 +08:00
    为啥不用 ts
    cutemurphy2888
        8
    cutemurphy2888  
    OP
       2022-11-21 09:28:55 +08:00
    @ospider 只有 50%的人在用·
    lisongeee
        9
    lisongeee  
       2022-11-21 10:03:07 +08:00
    看例子感觉不如<https://github.com/immerjs/immer> 好用
    cutemurphy2888
        10
    cutemurphy2888  
    OP
       2022-11-21 10:25:09 +08:00
    @lisongeee 我看看·
    xingguang
        11
    xingguang  
       2022-11-21 15:57:07 +08:00
    lodash 也有 merge 相关的库吧,没有必要重复造轮子,如果想要 render 的话就封装一个,用 useState 触发下 render
    hb751968840
        12
    hb751968840  
       2022-11-21 17:31:52 +08:00
    ts 还是有必要的,参考一下三年前写的 https://github.com/H-jx/use-model , 支持 immer.js 、immutable ,ts 自动推导
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3306 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 42ms · UTC 11:58 · PVG 19:58 · LAX 03:58 · JFK 06:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.