Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何更优雅地使用 Redux

如何更优雅地使用 Redux

原创
作者头像
陈津
修改于 2017-09-06 01:36:50
修改于 2017-09-06 01:36:50
2.7K0
举报
文章被收录于专栏:陈津的专栏陈津的专栏

业务背景介绍:腾讯云数据库产品中心 & 大数据及人工智能产品中心 前端从2016年初开始尝试 React + Redux 全家桶,期间经历了很多波折,到目前为止总共28个项目,其中有15个项目使用了该方案

一、Redux开发噩梦

Redux 在我看来除了提供统一的状态管理,最大好处就是实现 视图、业务逻辑 与 数据处理的分离,这样可以最大程度地去复用三个模块。

图:Redux 对项目的模块拆分

从这种意义上来说,它是成功的,但是实际的开发过程中,却遇到很多问题,导致开发体验非常不友好。

1、丑陋的switch case

做过 Redux 开发的一定对 Reducer 不陌生,里面主要靠 switch case 来处理 action。对于一个状态复杂的应用,一般使用 combineReducers来进行模块拆分,进而减少switch case的长度,使得模块化的 Reducer 可维护。实际应用中,往往比较考验开发者的模块划分能力,一些比较复杂的模块,不进行很好的拆分和重构,伴随着业务的变化 switch case 任然会增长很长。但如果你拆分得过细,Reducer与应用的状态树就会变得复杂。

下面是一个典型的表格 reducer:

代码语言:txt
AI代码解释
复制
var initailState = {
    columns,
    isLoading: true,
    list: [],
    result: undefined,
    selectedSet: new Set(),
    searchKey: ''
};

export default function (state = initailState, action) {
    switch (action.type) {
        case actions.ON_SEARCH:
            return {
                ...state,
                searchKey: action.searchKey
            };
        case actions.ON_TABLE_RELOAD://重新加载
            return {
                ...state,
                isLoading: true,
                selectedSet: new Set()
            };
        case actions.ON_TABLE_LOADED://加载完成
            return {
                ...state,
                isLoading: false,
                list: action.result && action.result.data && action.result.data.mixIpList || [],
                result: action.result
            };
        case actions.ON_TABLE_ALL_CHECK_CHANGE://全选
        {
            const {isCheck} = action,
                {list} = state;
            let selectedSet = new Set();
            if (isCheck) {
                list.map((item)=>selectedSet.add(item.id));
            }
            return {...state, selectedSet};
        }
        case actions.ON_TABLE_ITEM_SELECT_CHANGE://选中一项
        {
            const {id, isCheck} = action;
            let {selectedSet, list} = state;
            if (isCheck) {
                selectedSet.add(id);
            } else {
                selectedSet.delete(id);
            }
            return {...state, selectedSet};
        }
        case actions.ON_PROJECT_LOADED:
        {
            if(state.list.length){
                var plist = action.list;
                var li = state.list.concat();
                li.forEach(function (vip) {
                    plist.forEach(function (proj) {
                        if(vip.projectId == proj.value){
                            vip.projectName = proj.text;
                        }
                    });
                });
                return {...state, list: li};
            }else{
                return state;
            }
        }
        default:
            return state;
    }
}

2、令人头晕的开发体验

Redux 要实现 视图、业务逻辑 与 数据处理的分离,其实默认要求开发者开发过程是纵向的,但实际的开发过程中,大多数人的开发过程是横向的,如下图:

图:开发过程

这就导致一个问题,开发者会在 Reducer、ActionCreator、View 三者来回切换开发,在阅读一个项目源码的时候,也需要来回切换查阅,才能清晰地知道某个模块的逻辑。当模块的 Action 足够多,足够复杂,并且你显示器又不够大的时候,上面的过程往往就会把你绕晕了。

二、如何更优雅地使用

经历了很多项目,我观察到 Reducer 的一个代码特点,大量的 switch case 下都是简单的数据加工合成新的状态子树,这里可以通过统一的扩展覆盖方式来实现这个目标。

首先,我将 Dispatch 的方法设计为:

代码语言:txt
AI代码解释
复制
dispatch({
    type: actions.ON_REPORT_LOAD_COMPLETED,
    report:{
        isLoadingError: false,
        original: result.data[0],
        compare: result.data.length > 1 ? result.data[1] : null,
    }
})

这样,依靠关键字 report 可以用来做 Reducer 匹配,对应 report里面的内容可以直接在原有状态子树的基础上扩展覆盖生成新的状态子树。

对应 report的 Reducer 设计如下:

代码语言:txt
AI代码解释
复制
function reportReducer(
    state = {
        isLoadingError: false,
        original:{},
        compare:{}
    },
    action) {
    let newState = {...state, ...action['report']};
    return newState;
}

按照上述的方法,我们就解决了switch case的问题,action.type在这里的作用就只有 Redux DevTools 的回溯才会用到。

还可以近一步地优化,可以写一个方法来返回 Reducer 方法,这样就不用再重复写相同 Reducer 的扩展逻辑,如下:

代码语言:txt
AI代码解释
复制
function autoReducerCreator(initializeState, id) {
    return (state = initializeState, action) => {
        let updateState = action[id];

        //没有更新的状态,不进行处理
        if(typeof updateState == 'undefined'){
            return state;
        }

        //只更新原始状态子树有的属性
        //let newState = {...state, ...action[id]};
        let newState = {};
        for(let key in state){
            if(updateState.hasOwnProperty(key)){
                newState = updateState[key];
            } else{
                newState = state[key];
            }
        }


        return newState;
    }
}

//生成 reportReducer
let reportReducer = autoReducerCreator({
    isLoadingError: false,
    original:{},
    compare:{}
}, 'report');

let mainReducer = autoReducerCreator({
    isLoadingError: false,
    title: '-',
    content: '-'
}, 'main');

//组合 reducer
let reducers = combineReducers({
    report: reportReducer,
    main: mainReducer
});

最后还可以近一步创建一个函数分析状态对象,自动生成 Reducer,使得接口调用更简单,对整个 Redux 状态树更直观,如下:

代码语言:txt
AI代码解释
复制
function combineAutoReducers(initializeState){
    let reducers = {};
    for(let key in initializeState){
        let subState = initializeState[key];
        reducers[key] = autoReducerCreator(subState, key);
    }
    return combineReducers(reducers);
}

combineAutoReducers({
    report:{
        isLoadingError: false,
        original:{},
        compare:{}
    },
    main:{
        isLoadingError: false,
        title: '-',
        content: '-'
    }
})

三、最后

回到第一张图 Redux 的本意应该是数据与业务分离,数据处理的代码被分割到 Reducer 里,而业务逻辑放到 ActionCreator 里,而上述的优雅方案从某种程度上来会打破这种设定。但我想说的是这是一种折中,将 Reducer 90%代码压缩掉,剩余10%的数据处理代码不可避免的分散到 ActionCreator里,经过实际项目经历,其他同事均反馈开发效率与代码阅读体验得到很大提升。

当然最后的这个工具也保留了对原生 Reducer 的兼容方法。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
NFT元宇宙发展能做什么?
NFT,元宇宙,Web 3.0...这些概念最近在互联网上引起了人们的留意。可是,可能仍是有很多人不知道这些概念的详细中心和延伸运用。比方,在未来虚拟经济的开展中,NFT(非同质令牌)能够用来做什么? 在虚拟世界中,NFT能够在树立可行的经济中发挥关键作用: 或许游戏在虚拟实践中的操作; 虚拟空间的房地产、数码产品生意等出资时机; 立异电子商务服务等等; 以及其他与未来元宇宙商场动态相关的可能性。
v-longbatuiguang2
2022/06/25
3690
NFT元宇宙发展能做什么?
Metaverse 和 NFT 市场 2023-2024 年的趋势
NFT 最早出现于 2014 年,但兴奋和狂热始于 2021 年,这显然是一个分水岭。这是 NFT 成为城里每个角落最受关注的问题的时候。OpenSea、Rarible、Magic Eden、LooksRare、NBA Top Shot、CryptoPunks、Atomic Market 等 NFT 市场的流行证明了 NFT 的成功。
飞机号dapp119
2023/02/17
5750
Metaverse 和 NFT 市场 2023-2024 年的趋势
数字藏品热潮之下,你必须知道的那些事儿
元宇宙(Metaverse)是利用科技手段进行链接与创造的,与现实世界映射和交互的虚拟世界,具备新型社会体系的数字生活空间。元宇宙并不仅仅是一个虚拟空间,它是互联网高度发展的产物,是与现实世界紧密结合的,能够促使生活更美好、产业更高效、世界更有序的未来数字世界。
科技旋涡
2022/06/28
2240
数字藏品热潮之下,你必须知道的那些事儿
NFT链游开发:NFT与元宇宙的联系
NFT全称(不行替代令牌),中文名非同质通行证,也译为不行替代通行证。这是一种独特的数字财物。  比特币等财物是能够交换的,也便是说所有的比特币都是一样的,能够交换。  可是,每个非齐次经过是不同的。非同质通行证的比如能够是艺术品或游戏,NFT的每个实例都是绝无仅有的。
LIULIANG
2022/06/10
4050
NFT链游开发:NFT与元宇宙的联系
什么是元宇宙?
元宇宙概念源自美国小说家尼尔.史蒂芬森于1992年初版的科幻小说《溃雪》(Snow Crash),书中描述了一个让人们化身为各种网络分身进行互动的虚拟世界 -「Metaverse」。「Meta」意为「超越」;「Verse」意为宇宙,组合成「元宇宙」,即为“超越宇宙”的概念:
微观技术
2022/12/29
1.4K0
什么是元宇宙?
2022-2023设计趋势ISUX报告· NFT虚拟形象篇(上)
1.1 虚拟形象的诞生-CryptoPunks 2017 年,正值以太坊生态开始发力之时,原本两个不在加密货币圈子的开发者机缘巧合之下带着一万多个像素头像来到了这个生态当中,并由此开发出了世界上第一个NFT项目——CryptoPunks。 原本是做移动 App 开发的两人 John 和Matt,致力于从手机游戏和实用程式到网络基础设施再到数位设计和艺术的各种项目。在 2017 年初团队从伦敦Punks场景和cyberpunk电影和小说中汲取灵感,制作开发了一个多元化像素角色生成器,并创造了许多充满朋克精神的
腾讯ISUX
2022/06/24
1.2K0
2022-2023设计趋势ISUX报告· NFT虚拟形象篇(上)
一文论述元宇宙、NFT及不可回避的Web3时代
像Steve Aoki和Gary Vee这样的名人,亦或者是迪士尼和耐克这样的品牌他们有什么共同点?答案是他们都在利用科技和数字资产世界中的新兴领域,价值数十亿美元的NFT市场似乎在一夜之间就实现了,这一切意味着什么?
小将
2022/04/19
3690
一文论述元宇宙、NFT及不可回避的Web3时代
元宇宙系统全面学习线路
问题导读 1.元宇宙已经发展了多少年? 2.元宇宙是什么? 3.元宇宙有哪些概念? 4.元宇宙支持技术有哪些? 5.元宇宙和VR有什么区别? 6.元宇宙有哪些机会? 7.元宇宙如何开发,有哪些赛道?
用户1410343
2022/01/26
1.1K0
元宇宙系统全面学习线路
MetaDaily|Cocos 助力淘宝共建电商元宇宙,NFT数字藏品受我国法律保护
近期,Cocos 推出社区版,实现对淘宝平台的支持。内容开发者和商家使用社区版 Cocos Creator,即可轻松实现将游戏一键发布至淘宝购物平台。
科技旋涡
2023/02/23
1940
MetaDaily|Cocos 助力淘宝共建电商元宇宙,NFT数字藏品受我国法律保护
NFT元宇宙,以及游戏的关系 金色财经
上个世纪九十年代被提出的元宇宙概念,突然在30年后的今天以另外一种形式“复活”,并且在NFT市场迎来了属于自己的高光时刻。元宇宙概念的渐热标志着NFT从最早的数字收藏拍卖场景向更加复杂和庞大的体系发展,在这个过程中游戏成为了元宇宙+NFT设计的重要载体,这三者各自的角色定位以及配合关系很容易混淆,本文将对三者的关系和协同配合做一个简单的梳理。
vx_Dapp9521
2021/11/03
9770
NFT元宇宙,以及游戏的关系 金色财经
元宇宙六大技术全景图
元宇宙是基于现实世界的虚拟空间,在虚拟世界中搭建社交、生活、甚至经济系统,实现现实世界和虚拟世界的融合。根据Pulsar,元宇宙将会是虚拟世界、电子商务、去中心化技术和社交媒体。
肉眼品世界
2021/12/01
1.8K0
元宇宙六大技术全景图
最近大火的 NFT 数字藏品是什么?
作者:腾讯云至信链负责人王乐庆 在谈区块链和 NFT 之前,需要先说说「元宇宙」。 什么是元宇宙? 一千个读者眼中就有一千个哈姆雷特,元宇宙也是如此,下面讲讲我个人对元宇宙的理解,元宇宙的英文名称叫 Metaverse,区别于当前真实的宇宙 Universe,Universe 是由原子组成的物理宇宙,Metaverse 是比特组成的数字宇宙,当前我们在物理宇宙中从事生活、生产,这里有我们的资产、人际关系等等。未来在元宇宙中也会如此,我们会在这一数字宇宙中从事生产、创作、教育等等,拥有我们全新的人际关
腾讯技术工程官方号
2022/01/06
3.7K1
本体技术视点 | 元宇宙时代,虚拟土地和传统房产如何实现增值?
早在2017年,区块链行业就诞生了一个类元宇宙的项目叫 Decentraland。简单说这个项目就是用区块链技术构建了一个虚拟空间,你可以用这个项目发行的 Token(MANA)来购买虚拟空间里的地块。随后,又出现了一款引爆全球的区块链游戏叫 Sandbox,玩家在这个游戏中同样可以使用 SAND 购买土地。
本体Ontology
2022/03/29
5030
本体技术视点 | 元宇宙时代,虚拟土地和传统房产如何实现增值?
Web 3.0 和元宇宙的疯狂未来
首先,我们需要了解去中心化网络是什么。我们现在拥有的 Web2 高度集中在大公司手中,但这正在迅速演变为 Web3。同时,Metaverse是互联网或虚拟世界将如何融合并融入我们的生活,我们将能够与之无缝互动。让我们在本文中进一步探讨 Web 3.0 和 Metaverse 之间的区别以及它们在未来将如何相互补充。
飞机号dapp119
2022/11/17
5550
Web 3.0 和元宇宙的疯狂未来
Portals 能否成为下一个 Decentraland?
Portals因加密资产交易所币安的入驻而受到关注。1月10日,Coindesk报道,Binance美国站将在Solana链上的元宇宙平台Portals上建立办公室,用于以虚拟方式提供最新消息、图表和事件。
用户9329036
2022/01/11
3810
Portals 能否成为下一个 Decentraland?
Metaverse、Web3 和 NFT 的必然性
NFT 的天文数字式增长是 2017 年初步创新、稳步建立的交易所和钱包基础设施以及宏观顺风的结果。
飞机号dapp119
2022/12/16
2880
Metaverse、Web3 和 NFT 的必然性
MetaDaily|三星将投资3500万美元覆盖拉美元宇宙计划,空客在Avalanche发行NFT数字藏品
Yuga Labs在社交媒体透露将于2023年3月启动BAYC元宇宙项目Otherside Second Trip。根据Yuga Labs官方发布的消息,“第二次异界之旅”会引入全新游戏环节和新的机制,并提供更多游戏化选项和高能娱乐性,BAYC、MAYC和Meebits持有者均可以在游戏里中直接使用NFT化身。此外,Yuga Labs还宣布与Improbable合作并使用后者提供的Otherside开发包(ODK)进行创建和定制头像,提升游戏化身体验。
科技旋涡
2023/02/23
2350
MetaDaily|三星将投资3500万美元覆盖拉美元宇宙计划,空客在Avalanche发行NFT数字藏品
没有区块链技术,元宇宙将无法扩展
我们将生活在两个平行的世界中:虚拟与现实,沉浸在这两个独立但又通过区块链技术连接的世界中。
小将
2022/05/09
1.2K0
没有区块链技术,元宇宙将无法扩展
数字物种,iNFT = AI + NFT
随着数字化的渗透,数字空间不断影响着我们的行为习惯,社交网络、网络应用、游戏等都是一种数字空间,为了进入其中我们需要构建一种虚拟身份。
mixlab
2021/10/25
1.1K0
数字物种,iNFT = AI + NFT
NFT数字藏品系统开发的显著特点
NFT,这种非同质的标志,其特征是其共同和共同的标志,其不行分割性,以及其无法相等交换。是根据区块链的记账技能,用于开展数字经济和价值网络。
vx-longbatuiguang1
2022/05/21
4050
NFT数字藏品系统开发的显著特点
推荐阅读
相关推荐
NFT元宇宙发展能做什么?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档