最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 译|在 React 中使用 Immer 管理不可变状态

    正文概述 掘金(Zz招锦)   2021-03-05   923

    译|在 React 中使用 Immer 管理不可变状态

    在 React 中,使用不可变状态可以快速且高效地比较更改前后的状态树。因此,每个组件可在执行任何成本很高的 DOM 操作之前,决定是否重新渲染。

    我希望你已经知道:

    像 Redux 这样流行的状态管理库也遵循着相同的理念。当我们使用 reducers(译者注:根级的 reduce 函数 reducer 拆分为多个 reducers)时,它期望我们不要改变状态,以避免产生任何的副作用。但是,对于容易出错的大型项目,手动实现不可变性可能不是最佳选择。

    Immer 简介与使用

    Immer 是一个小型库,它基于写时拷贝(copy-on-write )机制帮助开发者实现不可变状态,这是一种用于在可修改资源上实现复制操作的技术。

    在 Immer 中,主要有三种状态:

    1. Current State:实际状态数据。
    2. Draft State:所有更改都将应用于此状态。
    3. Next State:该状态是基于 Draft State 的变化而产生的。

    译|在 React 中使用 Immer 管理不可变状态

    从性能的角度来看,与使用 JavaScript 中的 object.assign() 或展开运算符的浅拷贝(Shallow Copy)相比,Immer 表现得可谓是相当的好。如果你有兴趣了解更多关于性能的比较方面的信息,请参考此文:Immer vs 浅拷贝 vs 不可变性的测试。 译|在 React 中使用 Immer 管理不可变状态

    Immer 还减少了实现上述基准测试结果所需编写的代码量,这也是 Immer 脱颖而出的原因之一。

    现在你已经基本了解 Immer,接下来我们来看一下,为什么 Immer 被公认为是解决不可变性的最佳方案之一。

    Immer 的工作原理

    如果你正在处理简单的状态,可能会觉得 Immer 正在使你的代码更复杂。但是,当涉及处理复杂的数据时,Immer 变得非常有用。

    为了更好地理解这一点,让我们看看著名的 React reducer 示例:

    export default (state = {}, action) => {
        switch (action.type) {
            case GET_ITEMS:
                return {
                    ...state,
                    ...action.items.reduce((obj, item) => {
                        obj[item.id] = item
                        return obj
                    }, {})
                }
            default:
                return state
        }
    }
    

    上述代码是一个 React-Redux 的典型简化示例,它使用 ES6 展开运算符,并深入到状态树对象的嵌套级别来更新值。我们可以使用 Immer 轻松地降低上述代码的复杂性。

    让我们来看看具体如何使用 Immer 降低上述代码的复杂性。

    import produce from "immer"
    
    export default produce((draft, action) => {
        switch (action.type) {
            case GET_ITEMS:
                action.items.forEach(item => {
                    draft[item.id] = item
                })
        }
    }, {})
    

    让我们看另一个示例,将 Immer 与 React 结合使用。

    import produce from "immer";
    
    this.state={
        id: 14,
        email: "stewie@familyguy.com",
        profile: {
          name: "Stewie Griffin",
          bio: "You know, the... the novel you've been working on",
          age:1
        }
    }
    
    changeBioAge = () => {
        this.setState(prevState => ({
            profile: {
                ...prevState.profile,
                age: prevState.profile.age + 1
            }
        }))
    }
    

    可以通过更改如下所示的状态来重构这段代码。

    changeBioAge = () => {
        this.setState(
            produce(draft => {
                draft.profile.age += 1
            })
        )
    }
    

    如你所见,Immer 极大地减少了代码行数并降低了代码复杂度。

    结合 Hooks 使用

    Immer 的另一个重要特性是它支持 React Hooks。Immer 使用一个名为 use-immer 的附加库来实现此功能。让我们来看一个示例,以便更好地理解。

    const [state, setState] = useState({
        id: 14,
        email: "stewie@familyguy.com",
        profile: {
          name: "Stewie Griffin",
          bio: "You know, the... the novel you've been working on",
          age:1
        }
      });
    
    function changeBio(newBio) {
        setState(current => ({
          ...current,
          profile: {
            ...current.profile,
            bio: newBio
          }
        }));
      }
    

    通过将 useState 替换为 useImmer Hook,我们可以进一步简化 Hooks 示例,还可以通过更改组件状态来更新 React 组件。

    import { useImmer } from 'use-immer';
    
    const [state, setState] = useImmer({
        id: 14,
        email: "stewie@familyguy.com",
        profile: {
          name: "Stewie Griffin",
          bio: "You know, the... the novel you've been working on",
          age:1
        }
     });
    
    function changeBio(newBio) {
       setState(draft => {
          draft.profile.bio = newBio;
        });
      }
    

    同样,我们也可以使用 Immer 将 ArraySets 转换为不可变的对象。通过 Immer 创建的 MapSet 会在对象发生改变时会报错,从而使开发者能够意识到对象发生改变的错误。

    除了在维持不可变方面之外,Immer 还可以通过降低代码库的复杂度,帮助我们维护一个编写良好且可读性强的代码库。

    本文总结

    根据我对 Immer 的使用经验,我相信 Immer 与 React 结合使用是一个不错的选择。它将简化项目代码,并通过设计帮助管理不可变状态。

    你可以通过参考文档找到更多关于 Immer 的信息。

    感谢大家的阅读!



    起源地下载网 » 译|在 React 中使用 Immer 管理不可变状态

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元