“某某,你过来看一下这4个页面,为啥同样的接口请求回来的数据,在这个页面的下拉框显示的数据顺序是这样的,在其他3个页面的下拉框中显示的数据顺序是那样的啊;还有这四个页面查看的东西有关联性,能不能只要在其中一个页面域名下拉框中选中了域名另几个页面也同步记住这个域名,不要自己去重新选择呀?”
在某一个下班的工作日,老大跟我说了这么一个小需求,当时心想这还不简单,前一个问题就是排序一下后一个问题把值记录在sessionStorage中就ok了,于是我愉快的下班了,准备第二天早晨来弄。结果第二天我却花费了一天的时间。。。
这四个页面分别是record,https,prot,advance; 对于第一个问题record页面的域名数据在select中按字母顺序展示,其它3个页面按照接口返回顺序展示。看代码确实如我所想record页面将域名数据按照domain字段的首字母进行了一个升序排序,然后我又去看了一下其它3个页面发现也排序了呀,这怎么回事,其它3个页面没生效?这么诡异。吭哧吭哧看代码,额......竟然是前辈粗心写错了排序函数,第一行代码粗一看没有什么问题,但是打印数据发现a与b是对象,domain是其中的域名字段,这么写当然找不到domain字段排序也就没有生效了😭
.sort((a, b) => a[0]?.domain.charCodeAt(0) - b[0]?.domain.charCodeAt(0)) // 改前
.sort((a, b) => a.domain[0].charCodeAt(0) - b.domain[0].charCodeAt(0)) // 改后
问题解决完了出于好奇看了一眼这个组件,咦,它不是兼容了没有子域名展示的情况嘛(record页面没有子域名,其它3个页面有子域名),那为啥record不用这个组件而要自己重新写一遍,更奇怪的是其它3个页面为啥使用组件时传入noHost参数不展示子域名,而又页面自己单独写子域名,这代码得多重复呀😂 难道会有什么隐藏bug,看了一下代码感觉没什么问题呀,于是果断将4个页面换成了同一个Domain组件,去除多余的重复代码:“选中删除,选中删除,好了,呼,看下页面效果” emmmmm, 页面请求报错了,接口参数[Object Object] o(╥﹏╥)o 。不慌不慌,肯定是参数解析出错了,回归代码。打印日志调试, domian是个对象,{domain, host}, 所以得改一下
const getDomain = useCallback((domain) => {
console.log('domain', domain)
setDomain(domain);
}, []); // 修改前
const getDomain = useCallback((domainObj) => {
const { domain, domainType } = domainObj;
setType(domainType);
setDomain(domain);
}, []);
emmm,那以前怎么没问题呀,看下domain传值的地方:额,难怪,我现在参数noHost是true😂
useEffect(() => {
change(noHost ? domain : { domain, host });
}, [domain, host, noHost, change]);
刷新页面再看效果,嗯,果然功能正常了,emmmmm,,,但是为啥重复请求了两次domian-list啊,再回归代码接着优化,额,对了,组件中会请求数据,那原先自己页面的域名,子域名数据请求就可以删掉了,那就不用存数据state了,嗯,代码量一下子少了好多呀,舒服😁 咦,record页面还有要使用domainlist的地方,存当前选中domain的type,用来判断页面的显示,emmmm,为了这么个字段,再请求一遍域名接口也太不划算了,公共组件中有全部数据,也知道选中的域名,那传回数据时将选中域名的type传回来不就行了。
useEffect(() => {
!!domain &&
!!domainList.length &&
setType(domainList.find((item) => item.domain === domain).domain_type);
}, [domain, domainList]);
至此第一个问题解决,顺便删除了冗余代码,减去了重复的接口请求。
来看第二个问题,在值change时存进sessionStorage中,并且在useState定义初始值时,从storage中取
const [domain, setDomain] = useState<string>(sessionStorage.getItem('report-domain') || '');
查看页面效果, 嗯,确实存进去了,切到其它页面,咦,确实取值了,因为看到以存的值发请求了,但是怎么又变回默认值又发了请求呢😂 还是得看代码, 看看初始更新domain值时是怎么更新的,,emmmm, else分支里能看明白就是拉取到域名列表将第一个值赋给它,
useEffect(() => {
if (location.state?.domain) {
setDomain(location.state?.domain);
} else {
if (domainList.length) {
setDomain(domainList[0].domain);
}
if (!noHost && hostList.length) {
setHost(hostList[0]);
}
}
}, [location.state, domainList, hostList, noHost]);
但是location.state?.domain是啥? location是啥, useLocation,咦,以前没用过,嗯,又能学习新知识了,看看官方解释:
const location = useLocation<{ domain: string }>();
简单来说就是获取页面url相关信息的,但没看到state相关参数啊,再接着google,额,原来是在跳转来的路由上通过state参数可以传递数据,但是我们这里并没有需要跳转到这个页面并携带数据的呀,估计是以前有场景后来没有了但是忘记删除代码了,所以这里每次进入组件都会走else分支并且获取第一个默认值,修改为:
useEffect(() => {
const storeDomain = sessionStorage.getItem('report-domain');
const storeHost = sessionStorage.getItem('report-host');
if (storeDomain) {
setDomain(storeDomain);
} else if (domainList.length) {
setDomain(domainList[0].domain);
sessionStorage.setItem('report-domain', domainList[0].domain);
}
if (storeHost) {
setHost(storeHost);
} else if (!noHost && hostList.length) {
setHost(hostList[0]);
sessionStorage.setItem('report-host', hostList[0]);
}
}, [domainList, hostList, noHost]);
验证页面功能,展示正常,功能正常,请求清爽没有重复,代码没有冗余了。