将TS模板页面集成到JS版CRA中时React-ApexCharts报TypeError
将基于TypeScript模板的create-react-app(CRA)页面集成到基于JavaScript模板的CRA应用中,已按照官方指南完成TypeScript兼容配置。但集成新页面后,渲染ReactApexChart组件时出现以下错误:
apexcharts.common.js:6 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'indexOf') at t.value (apexcharts.common.js:6:1) at t.value (apexcharts.common.js:6:1) at t.value (apexcharts.common.js:6:1) at t.value (apexcharts.common.js:6:1) at t.value (apexcharts.common.js:14:1) at t.create (apexcharts.common.js:6:1) at apexcharts.common.js:14:1 at new Promise (<anonymous>) at t.value (apexcharts.common.js:14:1) at r.value (react-apexcharts.min.js:1:1)
该错误在纯TypeScript应用中不存在,仅在集成后的应用中出现。已通过浏览器调试确认props和状态传递正常,也排查了版本兼容性并尝试了多个react-apexcharts版本,但问题仍未解决。以下是相关代码与配置:
自定义Chart组件
const ChartCustom: FC<IChartProps> = ({ series, options, type, width, height, className, ...props }) => { return ( // eslint-disable-next-line react/jsx-props-no-spreading <div className={classNames('apex-chart', className)} {...props}> <ReactApexChart options={{ colors: [ process.env.REACT_APP_PRIMARY_COLOR, process.env.REACT_APP_SECONDARY_COLOR, process.env.REACT_APP_SUCCESS_COLOR, process.env.REACT_APP_INFO_COLOR, process.env.REACT_APP_WARNING_COLOR, process.env.REACT_APP_DANGER_COLOR, ], plotOptions: { candlestick: { colors: { upward: process.env.REACT_APP_SUCCESS_COLOR, downward: process.env.REACT_APP_DANGER_COLOR, }, }, boxPlot: { colors: { upper: process.env.REACT_APP_SUCCESS_COLOR, lower: process.env.REACT_APP_DANGER_COLOR, }, }, }, ...options, }} series={series} // @ts-ignore type={type} width={width} height={height} /> </div> ); };
package.json
{ "name": "qconnect-client", "version": "0.1.0", "private": true, "dependencies": { "@chakra-ui/icons": "2.0.17 ", "@chakra-ui/react": "2.4.9", "@emotion/react": "^11.10.6", "@emotion/styled": "11.8.1", "@hello-pangea/dnd": "^16.2.0", "@natscale/react-calendar": "0.0.0-beta.23", "@omtanke/react-use-event-outside": "^1.0.1", "@popperjs/core": "^2.11.6", "@reactour/tour": "^3.2.1", "@reduxjs/toolkit": "1.8.1", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "@types/jest": "^29.5.1", "@types/node": "^18.16.5", "@types/react": "^18.2.6", "@types/react-dom": "^18.2.4", "apexcharts": "^3.40.0", "axios": "0.27.2", "chart.js": "3.9.1", "chartjs-chart-treemap": "2.0.2", "chroma-js": "2.4.2", "classnames": "^2.3.2", "date-fns": "^2.29.3", "dayjs": "^1.11.7", "env-cmd": "10.1.0", "formik": "^2.2.9", "framer-motion": "^9.1.7", "i18next": "^22.4.10", "i18next-browser-languagedetector": "^7.0.1", "i18next-http-backend": "^2.1.1", "jsx-to-string": "^1.4.0", "lodash": "4.17.21", "moment": "^2.29.4", "pascalcase": "^2.0.0", "payment": "^2.4.6", "prismjs": "^1.29.0", "prop-types": "^15.8.1", "qs": "6.11.0", "randomcolor": "0.6.2", "react": "^18.2.0", "react-apexcharts": "^1.4.0", "react-big-calendar": "^1.6.8", "react-chartjs-2": "4.1.0", "react-credit-cards": "^0.8.3", "react-date-range": "^1.4.0", "react-datepicker": "4.8.0", "react-dom": "^18.2.0", "react-i18next": "^12.2.0", "react-image-webp": "^0.8.0", "react-input-mask": "^2.0.4", "react-jss": "^10.10.0", "react-modern-calendar-datepicker": "^3.1.6", "react-moment": "1.1.2", "react-notifications-component": "^4.0.1", "react-number-format": "^5.1.3", "react-popper": "^2.3.0", "react-redux": "8.0.1", "react-router-dom": "^6.8.1", "react-router-hash-link": "^2.4.3", "react-scripts": "5.0.1", "react-scrollspy": "^3.4.3", "react-syntax-highlighter": "^15.5.0", "react-toast-notifications": "^2.5.1", "react-transition-group": "^4.4.5", "react-use": "^17.4.0", "redux-logger": "3.0.6", "redux-thunk": "2.4.1", "use-clipboard-copy": "^0.2.0", "web-vitals": "^3.1.1", "yarn": "1.22.19", "@ionic/cli": "^7.1.1", "react-icons": "^4.8.0", "swiper": "^9.2.4" }, "scripts": { "start": "react-scripts start", "start:prod": "env-cmd -f ./.env.prod npm run-script start", "build": "react-scripts build", "build:prod": "env-cmd -f ./.env.prod npm run-script build", "test": "react-scripts test", "eject": "react-scripts eject", "serve": "serve -s build", "lint": "eslint .", "lint:fix": "eslint --fix --ext .js --ext .ts --ext .jsx --ext .tsx ./src", "lint:scss": "stylelint **/*.scss", "lint:fix-scss": "stylelint --fix **/*.scss", "icon": "svgr SvgIcons -d src/components/icon/svg-icons --typescript", "storybook": "start-storybook -p 6006", "storybook-withoutCache": "start-storybook -p 6006 --no-manager-cache", "build-storybook": "build-storybook" }, "_moduleAliases": { "@modules": "build/modules", "@core": "build/core" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version", ">0.2%" ] }, "devDependencies": { "@faker-js/faker": "6.3.1", "@svgr/cli": "^6.5.1", "@types/pascalcase": "^1.0.1", "@types/payment": "^2.1.4", "@types/prismjs": "^1.26.0", "@types/react-big-calendar": "^1.6.0", "@types/react-credit-cards": "^0.8.1", "@types/react-date-range": "^1.4.4", "@types/react-input-mask": "^3.0.2", "@types/react-router-hash-link": "^2.4.5", "@types/react-scrollspy": "^3.3.5", "@types/react-syntax-highlighter": "^15.5.6", "@types/react-transition-group": "^4.4.5", "@whitespace/storybook-addon-html": "^5.1.1", "animate.css": "^4.1.1", "bootstrap": "^5.2.3", "eslint": "^8.34.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-prettier": "^8.6.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "@typescript-eslint/eslint-plugin": "^4.7.0", "@typescript-eslint/parser": "^4.7.0", "prettier": "^2.8.4", "react-scripts": "5.0.1", "sass": "^1.58.3", "sass-loader": "^13.2.0", "source-map-loader": "^4.0.1", "storybook-addon-jsx": "^7.3.15-canary.162.1301.0", "stylelint": "^15.2.0", "stylelint-config-prettier-scss": "^0.0.1", "stylelint-config-standard": "^30.0.1", "stylelint-config-standard-scss": "^7.0.1", "stylelint-config-twbs-bootstrap": "^7.0.0", "stylelint-declaration-block-no-ignored-properties": "^2.7.0", "stylelint-declaration-strict-value": "^1.9.2", "stylelint-no-px": "^1.0.1", "stylelint-order": "^6.0.2", "stylelint-prettier": "^3.0.0", "stylelint-scss": "^4.4.0", "trim-newlines": "^4.0.2", "ts-loader": "^9.4.2", "tsconfig-paths": "^4.2.0", "typescript": "^4.4.0", "webpack": "5", "webpack-cli": "^5.0.2" }, "jest": { "transformIgnorePatterns": [ "<rootDir>/node_modules/(?!pascalcase|prismjs|@omtanke/react-use-event-outside/.*)" ] }, "resolutions": { "glob-parent": ">=5.1.2", "json5": ">=2.2.2", "nth-check": ">=2.1.1", "trim": "^1.0.1" }, "overrides": { "glob-parent": ">=5.1.2", "json5": ">=2.2.2", "nth-check": ">=2.1.1", "trim": "^1.0.1" } }
tsconfig.json
{ "ts-node": { "require": ["tsconfig-paths/register"] }, "compilerOptions": { "outDir": "./dist/", "sourceMap": true, "strictNullChecks": true, "module": "CommonJS", "jsx": "react-jsx", "target": "ESNext", "allowJs": true, "skipLibCheck": true, "lib": ["es5", "es6", "es7","DOM"], "moduleResolution": "node", "rootDir": "src", "emitDecoratorMetadata": true, "experimentalDecorators": true, "esModuleInterop": true, "noImplicitAny": true, "strict": true, "resolveJsonModule": true, "baseUrl": ".", "paths": { "@modules/*": ["src/modules/*"], "*": ["node_modules/*"] }, "allowSyntheticDefaultImports": true, "typeRoots" : ["node_modules/@types", "src/type"] }, "include": [ "./src/**/*", "./src/index.d.ts", "./src/declaration.d.ts" ], "exclude": [ "node_modules", "./node_modules", "./node_modules/*" ] }
排查方向与解决方案
环境变量未正确注入导致颜色值为undefined
组件中直接使用process.env.REACT_APP_*_COLOR,若这些变量在JS模板CRA中未正确加载(如.env文件位置错误、变量名拼写偏差、env-cmd配置差异),会导致colors数组出现undefined值,ApexCharts处理颜色时触发indexOf错误。
解决:在组件内打印process.env.REACT_APP_PRIMARY_COLOR确认值是否存在;检查.env文件是否在项目根目录,变量名完全匹配;临时将colors替换为固定十六进制颜色值,验证错误是否消失。TypeScript与JavaScript的模块解析差异
tsconfig中module设为CommonJS,而JS模板CRA默认使用ES模块,可能导致apexcharts加载方式冲突,内部模块未正确初始化。
解决:将tsconfig的module改为ESNext;或在组件中显式导入import ApexCharts from 'apexcharts',确保ReactApexChart能获取正确的依赖实例。重复依赖或版本不匹配
混合环境下可能存在重复安装的apexcharts依赖(如JS项目原有旧版本,集成TS后又安装新版本),导致实例冲突。
解决:删除node_modules和package-lock.json/yarn.lock,重新安装依赖;检查锁文件中是否存在多个apexcharts版本,确保仅保留^3.40.0版本。ReactApexChart的类型断言问题
使用// @ts-ignore忽略type属性的类型检查,可能在JS环境下type值不符合ApexCharts预期(如传入undefined或非字符串类型)。
解决:确认type参数实际值为ApexCharts支持的类型(如'line'/'bar'等字符串);移除@ts-ignore,给IChartProps的type字段定义正确类型,例如type: keyof typeof ApexCharts.CHART_TYPES。
内容的提问来源于stack exchange,提问作者Lokeshwar Tabjula

