持续创作,加速成长!这是我参与「掘金日新计划 · 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 tabIndex | react 中黑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模式下,安装后依赖报错:无法找到模块 | ts不能识别安装的依赖引用 | 在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::unsupported | node版本不合适,一般要将降低版本 | - |
| 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 |
| TS中组件忘记return或者返回类型未定义为:JSX.Element | 同原因 | |
| webpack启动应用:Uncaught ReferenceError: regeneratorRuntime is not defined | 1. 脚本使用了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,
]
})