背景
最近参与开发了一个模型训练的项目,有一个模型管理的新建页面
此页面的功能有两项
- 可以新建模型 + 新建版本
2. 可以基于已有模型新建版本
交互要求
对于第一种情况,新建模型 + 新建版本后,要跳转到新建模型的详情页,展示版本列表;
对于第二种情况,只是新增版本,此时就要跳转到已有模型的详情页,展示版本列表;
以上是基本的交互要求;
实现思路
我们通过页面路由查询字符串中是否有modelId
来进行两种情况的区分
针对第一种模式,无 modelId
, 用户点击提交,会先去创建 模型,此时后端会返回模型 id
,再基于此模型id
,创建版本, 并跳转至新创建的模型id
对应的详情页;
第二种,有了 modelId
,会直接创建版本,并在创建完跳转到此modelId对应详情页面;
第一版实现:
代码如下所示, 如按下述代码所示,modelIdTemp
在新建模型后的值没有做清空 ,此时就会出现其它模型在新建版本的时候,在触发页面跳转的时,都没有正确跳转到指定模型的详情页,而是跳转到 modelIdTemp
缓存模型id
值的对应得模型详情页,这就是所谓的乌龙也就是 bug 的症结所在。
jsx
/**
* modelId 通过查询字符串传递过来(基于模型创建版本会有)
* modelParams:创建模型需要的参数
* taskParams: 创建任务需要的参数
* navigate: 为 react-reouter-dom v6 中页面路由跳转使用
*
* 以下代码为简略版
*
*/
import {message} from 'antd';
let modelIdTemp;
const ModelAdd = () => {
/**
* 保存提交
*/
const handleSubmit = () => {
if (modelId) {
// 基于已有模型 新建 版本
handleSaveTaskInfo(modelId);
} else {
// 新建模型 + 新建版本
saveModelInfo(modelParams)
.then((res) => {
if (res.code === 0) {
// 后端返回模型Id 保存到 modelIdTemp 中
modelIdTemp = res.data;
// 创建任务
handleSaveTaskInfo(res.data);
} else {
message.error(res.message || "模型创建失败");
}
})
.catch((e) => {
console.log("模型创建失败~", e);
});
}
};
/**
* 创建任务
*/
const handleSaveTaskInfo = (id) => {
saveTaskInfo(taskParams, id)
.then((res) => {
if (res.code === 0) {
message.success("创建任务成功");
// 跳转到模型详情页
navigate(`/model/detail/${modelIdTemp || modelId}`);
} else {
message.error(res.message || "创建任务失败");
}
})
.catch((e) => {
console.log("创建任务失败~", e);
});
};
return <>
页面内容区域
</>
}
export default ModelAdd;
解决方法
可以解决的思路有:
- 在页面卸载的时候,将
modelIdTemp
重新置为空即可
jsx
useEffect(() => {
return modelIdTemp = '';
}, [])
- 使用
useRef
来解决
jsx
import { useRef } from "react";
import {message} from 'antd';
const ModelAdd = () => {
let modelIdTemp = useRef();
/**
* 保存提交
*/
const handleSubmit = () => {
if (modelId) {
// 基于已有模型 新建 版本
handleSaveTaskInfo(modelId);
} else {
// 新建模型 + 新建版本
saveModelInfo(modelParams)
.then((res) => {
if (res.code === 0) {
// 后端返回模型Id 保存到 modelIdTemp 中
modelIdTemp.current = res.data;
// 创建任务
handleSaveTaskInfo(res.data);
} else {
message.error(res.message || "模型创建失败");
}
})
.catch((e) => {
console.log("模型创建失败~", e);
});
}
};
/**
* 创建任务
*/
const handleSaveTaskInfo = (id) => {
saveTaskInfo(taskParams, id)
.then((res) => {
if (res.code === 0) {
message.success("创建任务成功");
// 跳转到模型详情页
navigate(`/model/detail/${modelIdTemp.current || modelId}`);
} else {
message.error(res.message || "创建任务失败");
}
})
.catch((e) => {
console.log("创建任务失败~", e);
});
};
return <>
页面内容区域
</>
}
export default ModelAdd;
使用建议
如果对于会发生变化的变量,建议 useRef
来 替代全局变量;