菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
96
0

还在用useState来定义数据吗?教你个更好的方案:useImmer!

原创
05/13 14:22
阅读数 1916

以前编写state的方式

Hooks上市之前我们是这么定义state的:

state = {
    people: [
      {
        name: '马云',
        englishName: 'Jack Ma'
      },
      {
        name: '马化腾',
        englishName: 'Pony Ma'
      },
      {
        name: '李彦宏',
        englishName: 'Robin Li'
      }
    ]
}

这种情况下如果用 setState({…}) 这种形式的话修改数据的话会比较麻烦,所以推荐函数式写法:

this.setState(state => {
    state.people[2].englishName = 'Robin Lee'
    return {...state}
});

函数式setState写法要求每次都返回一个新的引用,在类组件走遍天下的那个时代,state这个变量几乎存储了此组件中的所有数据,便于集中访问与管理。

Hooks时代

用了函数式组件定义数据就不能再这么定义了,假如你要是还像以前一样那么写:

const [state, setState] = useState({
    people: [
      {
        name: '马云',
        englishName: 'Jack Ma'
      },
      {
        name: '马化腾',
        englishName: 'Pony Ma'
      },
      {
        name: '李彦宏',
        englishName: 'Robin Li'
      }
    ]
});

那么你的setState就不太好改了,相信用过React Hooks的小伙伴们都能懂,而且这也不是被推荐的写法,一般来说我们会尽可能的细分:

const [jack, setJack] = useState({
    name: '马云',
    englishName: 'Jack Ma'
});
const [pony, setPony] = useState({
    name: '马化腾',
    englishName: 'Pony Ma''
});
const [robin, setRobin] = useState({
    name: '李彦宏',
    englishName: 'Robin Li'
});

这样的话修改数据就方便多了,粒度也更细腻,但是就是写起来麻烦、不够直观、代码量也更多,尤其是当你的数据量比较大、或者嵌套层级比较深的情况下那简直就是一场灾难。

那么怎么样才能既像以前setState那样方便快捷,同时又能使用函数式组件呢?聪明的朋友们应该猜也猜到了:useImmer

use-immer

来看看useImmer是怎么撰写上述逻辑的:

// 定义
const [state, setState] = useImmer({
    people: [
      {
        name: '马云',
        englishName: 'Jack Ma'
      },
      {
        name: '马化腾',
        englishName: 'Pony Ma'
      },
      {
        name: '李彦宏',
        englishName: 'Robin Li'
      }
    ]
})

// 修改
setState(state => {state.people[2].name = 'Robin Lee'})

无论嵌套层级多么深,无论数据有多么复杂,useImmer总能让你找到当年 this.setState(state => state.people[2].name = 'Robin Lee') 的感觉,但是不同之处除了一个要用 this. 而另一个不用以外还有一个需要注意的地方:

原生的setState直接可以当作返回值,而这个useImmer生成的盗版useState修改后的值不能被直接当作返回值返回,所以需要在函数体外面有大括号。
当然也可以自定义返回值,返回什么值就会更新成什么值。
喜欢我文章的朋友记得关注+点赞啊!

发表评论

0/200
96 点赞
0 评论
收藏