最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Say Bye to useState

    正文概述 掘金(chenbj)   2020-12-13   405

    前言:在最近的业务组件中,我完全使用useReducer代替了useState,并且因此感受到较大的开发快感,以至于我觉得完全可以尽可能地使用useReducer来代替useState

    why not useState?

    我们先说下useState哪里不好。

    以一个列表的展示为例,简单的发请求然后渲染列表,我们看看有哪些我们需要关心的state:

    • isLoading: 当true时,我们要展示Loading组件
    • listData: 当获取到后端返回的数据后,如果是空列表,展示NoData组件,如果是有值,则展示List组件渲染列表数据
    • error: 当请求失败时获得,展示Error组件

    如果看看每个state都用一个useState来创建代码会是怎样的:

    const [loading, setLoading] = useState(false);
    cosnt [listData, setListData] = useState([]);
    const [error, setError] = useState(null);
    
    const getListData = () => {
    	setLoading(true);
            service.post(url, params).then(res => {
                setListData(res.data.listData);
                setLoading(false);
            }).catch(err => {
                setError(error);
                setLoading(false);
            })
    }
    

    这样的代码的问题再哪里呢?

    这种代码,当代码执行到某个改变state的节点时,阅读者仅仅能确定某个state被set成了新值,但不明确这个/这些set动作具体的含义是什么,也不明确set之后组件整体是什么样子的

    比如我执行到catch中的的代码的时候,我知道你执行了setError(error); setLoading(false);,但是我问你,两个set具体描述了一个什么动作,set之后整个组件是个什么状态?

    对于这个例子,你数秒内就能说出来,这是show error的动作,set之后组件是一个展示Error子组件的状态。

    然而你之所以可以这么快的说出来仅仅是因为这个例子太简单了,如果这里一坨if else, set了一坨state,你还有信心能这么快回答出这个问题吗?

    理清状态的改变是读懂业务代码的关键所在,相信绝大多数人都浪费过时间在理清业务代码的状态上,并感受到不爽。

    然而useReducer就能有效地帮助我们解决这个问题,书写出状态流转明确的代码。

    how useReducer work?

    在我的理解中useReducer这个Api最重要的两个作用就是:

    • 给set动作起名
    • 给set之后的状态起名

    让我们看看用useReducer的思路:

    const reducer = (state, action) => {
    	switch (action.actionType) {
                    case 'REQUEST_SRART':
                        return {
                        	...state,
                            stateType: 'LOADING',
                            loading: true
                        };
                    case 'REQUEST_SUCCESS':
                        return {
                            ...state,
                            stateType: action.listData.length === 0 ? 'NO_DATA' : 'HAS_DATA',
                            loading: false,
                            listData: action.listData
                        };
                    case 'REQUEST_FAIL':
                        return {
                            ...state,
                            stateType: 'ERROR',
                            loading: false,
                            error: action.error
                        }
                    default:
                        return state;
             }
    }
    
    const [state, dispatch] = useReducer(reducer, {});
    
    const getListData = () => {
    	dispatch({
        	actionType: 'REQUEST_SRART'
        })
        service.post(url, params).then(res => {
            dispatch({
                actionType: 'REQUEST_SUCCESS',
                listData: res.data.listData
            })
        }).catch(err => {
            dispatch({
                actionType: 'REQUEST_FAIL',
                error
            })
        })
    }
    

    通过useReducer,任何的状态变更的动作都通过actionType进行了命名,变更后的组件状态也有了stateType进行描述,这使得代码的可读性大大提升。

    more about useReducer...

    最后我还想分享一下我使用useReducer书写业务组件的一些相关经验。

    通常来说,对于一个不过于复杂的功能,我们可以在这个功能模块的根组件中使用useReducer来产生整个组件需要的state和修改state的dispatch方法,我们首先通过书写reducer来理清整个组件的状态流转过程,然后再通过useEffect来写effect逻辑。

    组件内产生并仅向下传递的状态就使用一个useReducer创建一个state就可以了,理想情况下子组件消费的都仅仅是这个state的衍生状态。

    如果子组件也需要修改这个唯一state,那么就在父组件中把dispatch传到子组件供其调用来修改。

    以上就是我这篇文章想表达的全部内容了,Thank you for reading~


    起源地下载网 » Say Bye to useState

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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