umi+react项目中,自定义hooks的封装

从自己的项目经验中,总结了为什么要封装自己的hooks:

  1. 当数据影响的页面很多时,类似消息推送的业务,之前的做法是将数据存到initialState,然后在数据需要修改的页面对数据进行监听。
    这样操作虽然可行,但是会很繁琐,每个页面都得监听数据,代码比较冗余,维护成本较高。

那我们能用什么方法呢,一开始,我想到的就是写一个公共组件,在组建引入该组件,然后把子组件的data和改变data的方法传过去。

//Socketpage.jsx
import React, { useEffect, useState } from "react";
import { useModel, useLocation } from "@umijs/max";
function Socketpage({ data, setData,mainkey }) {
    const { initialState,setInitialState } = useModel('@@initialState');
    const { pathname } = useLocation();
    useEffect(() => {
        if (mainkey.indexOf(pathname) != -1) {
            let newData = JSON.parse(JSON.stringify(data));
            let cursocketdata = [], rowKey = '', operationtype = '';
            if (initialState.socketdata && Object.keys(initialState.socketdata).length > 0) {
                Object.entries(initialState.socketdata).map(([curkey, curoute]) => {
                    if (curkey == mainkey) {
                        cursocketdata = curoute?.data;
                        rowKey = curoute?.rowKey;
                        operationtype = curoute?.type;
                    }
                });
            }
            cursocketdata.map(item => {
                if (operationtype === 'add') {
                   newData.unshift(item);
                } else if (operationtype === 'update') {
                    newData = newData?.map(it => {
                        if (it[rowKey] === item[rowKey]) {
                            return {
                                ...it,
                                ...item
                            }
                        } else {
                            return it;
                        }

                    });
                } else if (operationtype === 'delete') {
                    newData = newData?.filter(it => it[rowKey] != item[rowKey]);
                }
            });
            setData(newData);
            setInitialState(s => {
                if (s.socketdata) {
                    delete s.socketdata[mainkey];
                }
                return {
                    ...s
                }
            })
        }
    }, [initialState.socketdata, pathname]);
    return <></>
}
export default Socketpage;
//在数据需要更新的页面,组件运用(随便写在哪一级,只要不是第一级的dom)
<Socketpage data={data} setData={setData} mainkey='/iot/devicelist/modela' />

但是你会发现Socketpage.jsx返回的其实相当于不用返回任何东西。此时就应该想到有没有更好的办法,那就是自己写一个ahooks,代码如下:

//useSocketBase.js
import React, { useEffect, useState } from "react";
import { useModel, useLocation } from "@umijs/max";

const useSocketBase = (data = [], setData, mainkey) => {
    const { initialState,setInitialState } = useModel('@@initialState');
    const { pathname } = useLocation();
    useEffect(() => {
        if(mainkey.indexOf(pathname) != -1) {
            let newData = JSON.parse(JSON.stringify(data));
            let cursocketdata = [], rowKey = '', operationtype='';
            if (initialState.socketdata && Object.keys(initialState.socketdata).length > 0) {
                Object.entries(initialState.socketdata).map(([curkey, curoute]) => {
                    if (curkey == mainkey) {
                        cursocketdata = curoute?.data;
                        rowKey = curoute?.rowKey;
                        operationtype = curoute?.type;
                    }
                });
            }
            cursocketdata.map(item => {
                if (operationtype === 'add') {
                    newData = newData.unshift(item);
                } else if (operationtype === 'update') {
                    newData = newData?.map(it => {
                        if (it[rowKey] === item[rowKey]) {
                            return {
                                ...it,
                                ...item
                            }
                        } else {
                            return it;
                        }
    
                    });
                } else if (operationtype === 'delete') {
                    newData = newData?.filter(it=>it[rowKey] != item[rowKey]);
                }
            });
            setData(newData);
            setInitialState(s=>{
                if (s.socketdata) {
                    delete s.socketdata[mainkey];
                }
                return {
                    ...s 
                }
            })
        }
    }, [initialState.socketdata,pathname]);
};
export default useSocketBase;	

//运用
const mainkey = '/iot/devicelist/modela';
const s = useSocketBase(data,setData,mainkey);

如果用过ahooks中useRequest的小伙伴都知道,这个hooks会暴露run,runAsync这些方法,所以之后我们可以根据业务,自定义hooks也可暴露出来一些方法,以便业务的调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值