React项目能否在useEffect内调用/public/assets/js下定义的JS变量
问题解答
能不能在useEffect内调用/public/assets/js下JS文件定义的变量?
完全可以,React本身是基于JavaScript的框架,不会限制你访问浏览器全局作用域下的原生JS变量。
报错原因分析
你遇到的控制台可访问、但useEffect内调用报错的情况,通常是两类原因导致的:
- 第一类:编译/类型检测阶段报错
React项目默认使用模块化开发规范,所有组件代码默认是模块作用域,你没有在当前模块声明的变量,ESLint(代码检测工具)或者TypeScript(如果是TS项目)会在编译阶段直接抛出can not find Name的错误。而Chrome控制台的执行上下文默认是全局window作用域,不需要经过项目的编译检测,只要全局存在该变量就能直接访问。 - 第二类:运行时脚本加载顺序问题
如果你引入test.js的方式是异步加载(比如加了async属性、或者动态创建script标签引入),很可能出现useEffect执行的时候,test.js还没加载完成,全局作用域下还没有jsVal变量,自然会抛出运行时错误。而你打开控制台的时候通常页面资源已经全部加载完成,此时访问jsVal自然是存在的。
修复方案
- 调整脚本加载顺序
打开/public/index.html,将test.js的引入script标签放在body标签的最底部、React项目入口脚本的前面,保证test.js同步加载完成后再执行React代码:<body> <div id="root"></div> <!-- 先引入自定义的全局JS --> <script src="/assets/js/test.js"></script> <!-- 再引入React项目的入口脚本 --> <script src="/static/js/bundle.js"></script> </body> - 解决编译检测报错
- 如果是ESLint报错,可以在调用
jsVal的组件代码顶部加全局变量声明注释:
也可以直接从window对象上明确取全局变量,不需要额外注释,同时增加判断避免加载异常:/* global jsVal */ import { useEffect } from 'react'useEffect(() => { // 先判断变量是否存在,避免加载未完成时报错 if (window.jsVal) { const existingScript = window.jsVal.getSum(); // 后续逻辑 } }, []) - 如果是TypeScript项目,需要新增全局类型声明,在
src目录下新建global.d.ts文件,添加如下内容:declare global { interface Window { jsVal: { getSum: () => number // 补充jsVal其他属性和方法的类型定义 } } } export {}
- 如果是ESLint报错,可以在调用
内容的提问来源于stack exchange,提问作者choding
相关产品推荐
相关产品推荐

