Ant Design Pro 源码分析之 ProLayout 中的 menu request 实现
Ant Design Pro 源码分析之 ProLayout 中的 menu request 实现
带着问题来研究源码。
版本
- “@ant-design/pro-layout”: “6.26.0”
起因
在使用 ProLayout 组件动态渲染菜单时,遇到了切换账号但没有触发 menu request 的问题。查了 issue,发现需要手动传递 params 来出发更新。想着深入了解一下这块儿的工作机制,研究一下源码。
经过
首先需要找到 pro-layout 源码以及引入位置,方便打 log 调试。经过查找,最终定位项目中引入的 pro-layout 位于 your_project/node_modules/@ant-design/pro-layout/es
路径下。
需要注意,经过测试:
- 每次修改 pro-layout 源码 ,需要重新
run start
- 需要关闭
mfsu
### 阅读源码
下面这段代码位于:your_project/node_modules/@ant-design/pro-layout/es/BasicLayout.js
var swrKey = useMemo(function () {
if (!(menu === null || menu === void 0 ? void 0 : menu.params)) return [defaultId];
return [defaultId, menu === null || menu === void 0 ? void 0 : menu.params];
}, [defaultId, stringify(menu === null || menu === void 0 ? void 0 : menu.params)]);
var preData = useRef(undefined);
console.log('swrKey: ', swrKey)
var _useSWR = useSWR(swrKey, /*#__PURE__*/function () {
console.log('in useSWR fetcher')
var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(_, params) {
var _menu$request;
var msg;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
setMenuLoading(true);
_context.next = 3;
return menu === null || menu === void 0 ? void 0 : (_menu$request = menu.request) === null || _menu$request === void 0 ? void 0 : _menu$request.call(menu, params || {}, (route === null || route === void 0 ? void 0 : route.routes) || []);
case 3:
msg = _context.sent;
setMenuLoading(false);
return _context.abrupt("return", msg);
case 6:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return function (_x, _x2) {
return _ref4.apply(this, arguments);
};
}(), {
revalidateOnFocus: false,
shouldRetryOnError: false,
revalidateOnReconnect: false
}),
data = _useSWR.data;
console.log('_useSWR.data: ', _useSWR.data)
preData.current = data; // params 更新的时候重新请求
console.log('preData.current: ', preData.current)
useEffect(function () {
if (!preData.current) {
return;
}
mutate(swrKey); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [swrKey]);
首先当我们在 layout config 中不传入入 menu params。
// in app.tsx
return {
menu: {
// params: {
// currentUser: initialState?.currentUser?.result?.current_user,
// },
request: async () => {
// https://pro.ant.design/zh-CN/docs/advanced-menu
const menuRes = await queryMenusData();
return mappingIcon(menuRes);
},
},
}
重新 run start
,登录账号 A,可以看到控制台打印出
swrKey: ['pro-layout-1']
切换为账号 B,发现 swrKey 值没变。之后没有触发 useSWR,查阅 SWR 文档, SWR 会对相同的 swrKey 做性能优护,只会请求一次数据。所以这边应该是没有触发 fetcher。
下面来测试传入 params。将 params 注释恢复为代码,
// in app.tsx
return {
menu: {
// params: {
// currentUser: initialState?.currentUser?.result?.current_user,
// },
request: async () => {
// https://pro.ant.design/zh-CN/docs/advanced-menu
const menuRes = await queryMenusData();
return mappingIcon(menuRes);
},
},
}
重复之前操作,退出账号 B,登录账号 A,观察控制单输出
swrKey:
(2) ['pro-layout-1', {…}]
0: "pro-layout-1"
1: {currentUser: 'myNameA'}
lastIndex: (…)
lastItem: (…)
length: 2
[[Prototype]]: Array(0)
发现 swrKey 多了一个对象,存放了 params 参数。此时再切换账号 B,发现菜单已经更新,观察控制台输出。
swrKey:
(2) ['pro-layout-1', {…}]
0: "pro-layout-1"
1: {currentUser: 'myNameB'}
lastIndex: (…)
lastItem: (…)
length: 2
[[Prototype]]: Array(0)
所以如果想要切换账号,或者说切换路由时重新执行 menu request
需要给 menu params
传入新值,触发 useMemo
, useSWR
更新。
本文参考
作者:hayato
文章版权:本站所有文章版权依赖于 CC BY-NC-SA 3.0 Unported License
本文链接:https://blog.axis-studio.org/2021/10/11/Ant-Design-Pro-源码分析之-ProLayout-中的-menu-request-实现/