React项目中TS报错解决方案

孔和风
2023-12-01

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)
        }
      };
    }
  }

未完待续…

 类似资料: