Umi&&React&&Vue3&&TS报错解决方案总结(个人向)
Redux开发工具报错window下没有某属性
解决方案,项目根目录创建global.d.ts文件
export { global }
/**
* 解决redux开发工具报错
*/
declare global {
interface Window {
// 属性为redux开发工具对应属性
// const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// const store = createStore(persistedReducer, composeEnhancers());
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: Function
}
}
Store中reducer因为接口问题报错,ts类型不能分配问题
将reducer声明处定位指定属性或者any即可
ts写法useRef声明报错问题
const child: any = useRef<ReactNode>(null)
其中null为初始化声明,ReactNode是子组件的类型推断,any防止子组件使用时报错,面向any的ts写法…
Umi开启热刷新后persisit冲突无法持久化
暂未解决,目前只好关闭热刷新,保证persist正常运行
redux-persisit刷新无法持久化?
需要关注reducer文件中是否使用不可变对象,或者正确结构,否则会被覆盖,推荐使用immer等不可变对象操作
echarts自适应多种设备的时候,事件监听无法关闭?
正难则反,将echart取出,在外部去监听并关闭时候取消监听
//echart组件中
useEffect(() => {
let { myChart } = initoneEchart()
// renderChart()
console.log(myChart);
const listener = () => {
// if (!myChart) {
// console.log(22);
// window.removeEventListener('resize', listener)
// }
console.log(11);
myChart && myChart.resize()
}
window.addEventListener('resize', listener)
return () => {
window.removeEventListener('resize', listener)
}
})
/** echart初始化 **/
// echarts
const initoneEchart = () => {
type EChartsOption = echarts.EChartsOption
let chartDom = document.getElementById('container')!;
let myChart = echarts.init(chartDom);
let option: EChartsOption;
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true
}
]
};
option && myChart.setOption(option);
return {
myChart
}
}
React报错Invalid hook call. Hooks can only be called inside of the body of a function component.
检查react版本是否大于16.8,是否将useHooks等用在组件头部(官方规定)
umi的useRequset结构以及fetch解构
umi的request,useRequset底层也是fetch封装,需要多一个then返回res对象并以res.json()方式序列化导出,推荐不可变对象进行深拷贝导出复制等操作
fetch('http://localhost:8000/api/users').then(res => res.json()).then(res => {
console.log(res);
})
umi的useModel使用问题
umi的plugin-initial-state使用问题
文档规定了在app.ts中写入一个async函数,注意,必须是async异步函数,否则报错,无法获取,且该插件必须与useModel搭配使用,即src/models 目录下有 hooks model 时启用.
useModel为umi封装的全局状态管理工具,后续微前端也推荐该方法使用进行父子项目通讯,
// src/app.ts
// 此处进行请求设置或者async异步操作警醒存取即可
export async function getInitialState() {
const data = await fetchXXX();
return data;
}
umi的plugin-initial-state使用后persist持久化报错问题
报错如下:TypeError: Cannot read properties of null (reading ‘_store’)
意思无法读取app.ts中缓存的数据,则无法拿到_store对象无法缓存,
缓存代码如下:
//其余代码没贴,此处是app.ts中dom更新及使用persist的diff计算并进行存储
window.addEventListener('DOMContentLoaded', () => {
const app = getDvaApp()
console.log(app, 997);
persistStore(app._store)
})
React模板字符串生成dom后点击事件触发问题
需求是使用高德地图,生成marker后,点击marker有infowindow窗口,然后点击关闭按钮关闭窗口
let infoWindow = initInfoWindow(e.data.name)
infoWindow.open(mapBox, [e.data.lnglat[0], e.data.lnglat[1]]);
//在生成infoWindow中的content内容区后,在进行dom获取和绑定,否则直接绑定会报错方法未定义及click事件不存在等错误
let dom1: any = document.getElementById('info_click')
dom1.onclick = () => {
mapBox.clearInfoWindow()
}
由于机制问题,会读取到空值,因此将DOMContentLoaded改为load即可正常
Umi-@qiankun配置微前端bug
报错1:Disconnected from the devServer, trying to reconnect…但可显示界面
**原因分析:**由于umi有node启动的环境以及websocket实施监听热刷新机制,因此,会出现该报错
方案一:配置的子应用socket端口应该放在主应用上
在/scr/.env文件中配置SOCKET_SERVER=‘主应用地址url’,但是,如果开发期间主应用没开启呢?那岂不是又要提示影响开发?
方案二:packjson中取消socket机制
在packjson中的启动项中加入如下代码
"start": "set PORT=8089 SOCKET_SERVER=none && umi dev",
重启一下即可
报错2:You are attempting to use a basename on a page whose URL path does not begin with the basename. Expected path “/” to begin with “/app1”
该报错并没爆红,但是出现了提示,有强迫症的哥们会想去掉,或者找到原因,于是…
方案1:在.umirc的配置中写入base路径?这个配置项目前被弃用,而且行不通
方案2:调整route的路径配置?虽然一定程度可行,但是等于重新调整结构,麻烦,且不彻底
方案3:在子应用中的umirc文件中得到defineConfig中写入base配置项为’/'即可,此时不报错,解决!
总结:报错1和报错2都是属于微应用的配置问题,如果出现配置后不生效问题,尝试重新刷新或者修改配置重启覆盖.umi文件的临时文件,或者删除.umi缓存重新修改,总之,可能是缓存导致没有生效,多尝试修改下即可
antd4版本中的upload组件业务bug解决
由于4版本的upload的事件仅有onChange无法像其他组件做到onSuccess一样处理,但是业务又要对成功的图片进行特殊处理,放到指定数组中并渲染视图**,且在onChange中写业务代码会有三次的执行特性,源于antd对上传的特殊处理,对此,有的版本会识别response.code==='‘200’'或者status==='done’去特殊识别,但是有的版本又无法通过该方法进行**,由此,我们考虑曲线救国,在beforeUpload事件中进行预处理,利用函数颗粒化beforeUpload={(e) => { handleBefore({ origin: e, upItem: item }) }},并在其中利用image的onload事件去处理成功上传后的业务代码
// beforeUpload={(e) => { handleBefore({ origin: e, upItem: item }) }}
const handleBefore = (e: any) => {
const { origin, upItem } = e
if (origin instanceof Blob) { // 类型检查
const img = new Image();
img.src = URL.createObjectURL(origin);
img.onload = () => {
URL.revokeObjectURL(img.src);
// 后续处理
if (upItem?.name === 'bills') {
// 业务代码
// createBillItem(1)
}
if (upItem?.name === 'udicode') {
// 业务代码
// createUdiItem(1)
}
};
}
}
未完待续…