前端开发中遇到的Error们(持续更新......)

2,326 阅读9分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

本文仅记录自己在日常开发过程中遇到的各种报错和数据异常问题。

React项目

问题排查原因解决方案
ndex.js:55 Warning: Cannot update a component (EmailCreateByAI) while rendering a different component (AIForm). To locate the bad setState() call inside AIForm, follow the stack trace as described in 。。。子组件中用了eventbus,在重渲染的时候发送了事件,父组件中接受到后触发了重渲染。但是一个 fiber 渲染周期,子组件渲染过程中,父组件是不能变为新的引用的如下
// 子组件
-  const submitDisabled = useMemo(() => {
  -    const values = formik.values || {};
  -    // 原来的代码,在 formik.values表单值变化时就发送事件,导致子组件重渲染时,发送了多次事件
  -    // 发布 submitDisabled 状态
  -    eventBus.publish(
  -      'submitDisabledState',
  -      !(
  -        values.Channels &&
  -        values.Channels.filter(Boolean).length &&
  -        values.Type &&
  -        values.Industry &&
  -        values.Tone &&
  -        values.Prompts &&
  -        values.Prompts.length
  -      )
  -    );
  -    return !(
  -      values.Channels &&
  -      values.Channels.filter(Boolean).length &&
  -      values.Type &&
  -      values.Industry &&
  -      values.Tone &&
  -      values.Prompts &&
  -      values.Prompts.length
  -    );
  -  }, [formik.values]);

// 修改后
  +  const submitDisabled = useMemo(() => {
  +    const values = formik.values || {};
  +    return !(
  +      values.Channels &&
  +      values.Channels.filter(Boolean).length &&
  +      values.Type &&
  +      values.Industry &&
  +      values.Tone &&
  +      values.Prompts &&
  +      values.Prompts.length
  +    );
  +  }, [formik.values]);
  +
  +  useEffect(() => {
  +    // 在副作用中发布事件,保证在渲染结束后执行
  +    eventBus.publish('submitDisabledState', submitDisabled);
  +  }, [submitDisabled]);
问题排查原因解决方案
safari中nextjs报错:Unhandled Runtime Error SyntaxError: Unexpected private name #parseMarkdown. Cannot parse class method with private name.因为项目中使用了依赖:"marked": "^10.0.0", 它不支持 safari 14- 的版本自己写一个.babelrc文件来兼容低版本:{"presets": ["next/babel"],"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-private-methods"]}, next.config.js 中写入 webpack配置:
webpack: (
    config,
    options,
  ) => {
    // Important: return the modified config
    config.module.rules.push({
      test: /\.js$/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
        },
      },
      include(path) {
        if (path.includes("marked")) {
          return true
        }
        if (path.includes("node_modules")) {
          return false
        }
      }
    })

    return config
  },
问题排查原因解决方案
Warning: Invalid DOM property %s. Did you mean %s?%s tabindex tabIndexreact 中黑DOM传递属性时应遵从驼峰写法改为 tabindex --> tabIndex
nextjs配置i18n后报错:TypeError: codes.forEach is not a function at LanguageUtil.getBestMatchFromCodes (webpack-internal:///(rsc)/./node_modules/i18next/dist/esm/i18next.js:951:15)配置i18n文件有问题对于 App Router,推荐按照这个文档配置:locize.com/blog/next-a…
react-dom.development.js:16451 Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering一般这样的错误会配套一个警告:Warning: validateDOMNesting(...): <head> cannot appear as a child of <div>,DOM结构错乱导致的检查dom树,看看是不是写了错误的级联渲染树
nextjs报错:react-dom.development.js:7076 Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.服务端与客户端渲染数据不一样,可能是写了两套page.js文件,两个文件内容还不一致导致的,应该保证同一个url访问只能有一个入口路由-
nextjs14+报错:Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".Next.js默认将所有在客户端运行的代码进行沙箱化,以防止XSS(跨站脚本)攻击,客户端组件不能接收任何的服务端异步函数在服务端组件中声明 "use server", 同时将一个异步函数(async)通过props传递给子组件,子组件此时可以标记为 'use client',当然你还可以写一个 error.(jsx|tsx) 文件来捕获错误
react的ts模式下,安装后依赖报错:无法找到模块 image.pngts不能识别安装的依赖引用在dev依赖安装对应模块依赖的@types格式 或者自定义声明对应的.d.ts文件
Objects are not valid as a React child出现的地方不止一处,都是把一个object当做数组了,因为React的花括号渲染children时必须是array形式。排查出现问题的文件中传参的正确性即可。
TypeError: Cannot read properties of null (reading '1')类似读不到null或者undefined的属性值,一般上就是对象传成了空,比如 info.name, 你的info如果没有初始化或者通过某种手段设置为了空,就会报这个错误1. 改写 info?.name
2. 如果是props值,使用之前需判空;如果是本组件内的变量,可以useState({}), 在setInfo的时候可以这样写setInfo(data || {})
Uncaught Error: You are trying to create a styled element with an undefined component. You may have forgotten to import it.使用styled对组件设置样式时,组件传了空const SelectInput = styled(Input.Search)中核对Input.Search不为空即可
A cross-origin error was thrown. React doesn't have access to the actual error object in development这种错误一般是 JSON.parse()传入了空-
TypeError: rawData.some is not a function使用了ant design的Table组件,官方要求dataSource应为数组, 实际上传了{}-
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.组件销毁时异步还没执行完毕,在异步执行完后发现找不到宿主了。检查各个组件,确保在组件销毁之后不在调用异步组件加载时设置isMounted = ture, 组件销毁时设置isMounted = false, 在必要的异步回调的地方加上isMounted判断即可
解决js-xslx库导出excel时,解析日期时间对不上的问题比较小众的问题,一个excel导出的插件,导出的时间格式总是与实际时间有误差,应该是时区不统一造成的安装一个依赖yarn add ssf,在导出的格式化中写入:moment(new Date(SSF.format("YYYY-MM-DD HH:MM:ss", item['失效时间']) + " GMT+0800")).format('YYYY-MM-DD HH:mm:ss')
Warning: Encountered two children with the same key...同一个循环列表里两个并列的item使用了相同的Key使用uuid代替,或者在保证安全的前提下使用index代替
Warning: [antd: Form.Item] name is only used for validate React element. If you are using Form.Item as layout display, please remove name instead.antd的form中表单元素要加上name属性,非表单元素不要加-
Maximum update depth exceeded.可能原因:在render期间setState造成的超量赋值操作,逐一排查,肯定有调用死循环 : 父组件render => 参数变化 => 触发子组件useEffect => 参数变化 => 回调父组件引起父组件该参数变化-
弹窗组件中也会有 Can't perform a React state update on an unmounted component我们不能在组件销毁后设置state,防止出现内存泄漏的情况在弹窗setVisible(false)后或者组件销毁函数中,不要再setState
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.写的组件忘记 export啦-
npm run dev 报错:Error: error:0308010C:digital envelope routines::unsupportednode版本不合适,一般要将降低版本-
index.tsx:24 Uncaught Error: [undefined] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>react-router-dom使用时的问题<NavLink>不要放到<Route>里, 直接放到<BrowserRouter>下就可以了
ReactDOM.render is no longer supported in React 18升级到react18后,ReactDOM下不再有render这个方法了使用ReactDOM.createRoot代替
antd的报错: Warning: Instance created by useForm is not connected to any Form element. Forget to pass form prop?这种情况一般是在Modal里的Form出现,一般原因是在初始化钩子调用form.setFieldsValue({})时,form还未来得及关联到元素上给Modal组件添加forceRender属性
类式组件中Uncaught SyntaxError: embedded: Unexpected token .token什么也没有,说明是state初始化问题直接写 state = {}是有问题的, 应该放在constructor中
在TS中使用装饰器: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.在tsconfig.json中缺少配置experimentalDecorators": true,
在TS中:Property '...' has no initializer and is not definitely assigned in the constructor构造器声明成员变量没有初始化。在tsconfig.json中缺少配置"strictPropertyInitialization": false
TS项目中:Failed to parse source map from '..Button.tsx' file: Error: ENO ENT: no such file or directory, open '..Button.tsx'webpack5的问题,识别不了node_module中的ts文件在根目录新建一个.env文件,加入:GENERATE_SOURCEMAP=false
image1.pngTS中组件忘记return或者返回类型未定义为:JSX.Element同原因
webpack启动应用:Uncaught ReferenceError: regeneratorRuntime is not defined1. 脚本使用了ES7的 async/await,regeneratorRuntime在浏览器上是不认识的,需要安装@babel/plugin-transform-runtime插件plugins: ['@babel/plugin-transform-runtime'], 或者在报错的文件最上边引入: import 'regenerator-runtime/runtime',或者在根组件下引入regenerator-runtime
webpack4,CRA项目下, React router 报错:Uncaught TypeError: path_to_regexp__WEBPACK_IMPORTED_MODULE_8___default.a.compile is not a function检查后发现是 react-router-dom的API:generatePath 执行报错需要第三方版本你库的支持:"path-to-regexp": "^1.7.0"
Uncaught (in promise) Error: Minified React error #321; visit reactjs.org/docs/error-… for the full message or use the non-minified dev environment for full errors and additional helpful warnings.很奇怪的错误,排查原因是把本来是字符串的ReactElement传为了 Object 类型的改正传值即可:formateMessage({ id: "U_TEXT" }) --> formateMessage('U_TEXT')

Angular项目

开发报错1:No component factory found for . Did you add it to @NgModule.entryComponents
排查原因 ng8-的版本,动态组件需要在entryComponents里声明
解决

同原因


开发报错2:ERROR TypeError: this.suiTableData.slice is not a function
排查原因 前端比较常见的问题,suiTableData作为组件input的数据,传了个空
解决

同原因


开发报错3:Type 'Map<string, string>' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.
排查原因 这是ts遍历map会出现的问题,下面给出两种解决办法
解决
//1
for(let [a,b] of Array.from( map.keys()) ) {
   console.log(a + ' ' + b);
}

//2
map.forEach((value: string, key: string) => {
    console.log(key, value);
});

开发报错4:No value accessor for form control with name: 'unitSelect'
排查原因 自定义的表单组件在ngForm中不受控
解决
// 在表单中加入ngDefaultControl 
<sui-select name="unitSelect" [(ngModel)]="calcIntervalUnit" ngDefaultControl>
开发报错5:core.js:7187 ERROR Error: Uncaught (in promise): Error: Unexpected value 'undefined' declared by the module 'StreamDetailModule'
排查原因 表面上是module引了个寂寞,实际上可能是重复引入了。
解决
//1. 父子两个index页面重复引用了detail-list组件
//2. 还可能的其他问题: import 时多写了一个逗号

单测报错1:An error was thrown in afterAll\nUncaught:Cannot convert undefined or null to object thrown
排查原因 FedAuthService的注入有问题

原写法:

  fetchTenantDetail() {
    this.tenantService.getTenantDetail(this.tenantName)
    .subscribe((tenant: TenantDetail) => {
      this.tenant = tenant;
      this.attrs = Object.entries(this.tenant && this.tenant.attributes);
    });
  }
{
  provide: FedAuthService,
  useValue: {
    isAuthenticated () {
      return observableOf();
    },
    isLoggedIn() {
      return observableOf();
    },
    purge() {
      return observableOf();
    }
  }
}

一行一行注释原来的component的逻辑代码,看是哪一行引入导致的错误,发现注释掉this.fetchTenantDetail()就不会报错了。进入该方法一层一层看,最终定位:

//括号里的可能为undefined
Object.entries(this.tenant && this.tenant.attributes)

解决
//改为
this.attrs = (this.tenant && this.tenant.attributes) ? Object.entries(this.tenant && this.tenant.attributes) : [];

// 或者在mock数据里给this.tenant.attributes附上初值。

单测报错2:TenantDetailAuthSourceComponent should registerAuthSource TypeError: this.modalService.registerAuthSourceModal is not a function
排查原因 该函数没有mock返回值
解决
{
  provide: TenantModalsService,
  userClass: TenantModalsServiceStub
},

class TenantModalsServiceStub {
  deleteTenantModal() {
    return observableOf();
  }
  registerAuthSourceModal() {
    return observableOf();
  }
  editAuthSourceModal() {
    return observableOf();
  }
}

单测报错3:TranslateModule报错:Invalid provider for the NgModule 'DynamicTestModule' - only instances of Provider and Type are allowed\
排查原因 测试用的module注入问题

查找网址Invalid provider for the NgModule找到解决方案。

解决
TranslateModule.forRoot({
  loader: {
    provider: TranslateLoader,
    useClass: (translateFactory)
  }
})

// Use `useFactory` instead of `useClass`. Use `provide` instead of `provider`.
// Use `@ngx-translate/core` instead of `ng2-translate`

单测报错4:There is no directive with "exportAs" set to "ngForm
排查原因 缺少FormsModule
解决
//在测试类中引入 FormsModule
import { FormsModule } from '@angular/forms';

 TestBed.configureTestingModule({
  schemas: [NO_ERRORS_SCHEMA],
  imports: [
    MockModule,
    FormsModule
  ],
  declarations: [
    ResourceMetricPropertyTableDesignComponent,
    TranslatePipeStub,
  ]
})