React部署WordPress报错:Uncaught SyntaxError: Unexpected token '<'求助
解决React组件在WordPress中使用时的语法错误
问题概述
开发了一个简单React组件,打包后在WordPress中通过短代码调用,运行时出现错误:Uncaught SyntaxError: Unexpected token '<' (at (index):452:25),尝试多种方案未解决。
相关代码如下:
React入口文件(index.js)
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <App /> );
React App组件
const App = ({ message }) => { return ( <div> <h1>{message}</h1> </div> ); }; export default App;
WordPress短代码钩子
function react_app_shortcode($atts) { $atts = shortcode_atts( array( 'message' => 'Default Message', ), $atts ); ob_start(); ?> <div id="react-app"></div> <script> const rootElement = document.getElementById('react-app'); const message = '<?php echo esc_js($atts['message']); ?>'; ReactDOM.render(<App message={message} />, rootElement); console.log("code is working") </script> <?php return ob_get_clean(); } add_shortcode('react_app', 'react_app_shortcode');
错误原因
- 浏览器无法解析JSX:WordPress输出的
<script>标签中直接使用了<App message={message} />这种JSX语法,浏览器原生JavaScript不支持JSX,必须编译为React.createElement调用才能执行。 - 组件未暴露为全局变量:打包后的React组件默认是模块化的,WordPress中的脚本无法直接访问
App和ReactDOM对象。 - React 18 API使用问题:原代码混用了React 18的
createRoot和旧版ReactDOM.render方法,虽然兼容但容易引发其他问题。
解决方案
步骤1:调整React组件打包配置,暴露全局变量
修改React项目的入口文件(index.js),将App组件暴露到全局window对象,同时保留本地开发的渲染逻辑:
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; // 将App组件暴露给全局,供WordPress调用 window.App = App; // 本地开发环境的渲染逻辑(仅在有root元素时执行) const localRoot = document.getElementById('root'); if (localRoot) { const root = ReactDOM.createRoot(localRoot); root.render(<App message="本地开发测试" />); }
然后执行打包命令(以Create React App为例):
npm run build
将打包生成的build/static/js/目录下的JS文件(如main-xxxx.js)复制到WordPress主题目录的dist/子目录中(没有则新建)。
步骤2:修改WordPress短代码函数
更新短代码,正确引入React、ReactDOM和打包后的组件,并用原生JavaScript替代JSX:
function react_app_shortcode($atts) { $atts = shortcode_atts( array( 'message' => 'Default Message', ), $atts ); // 引入React、ReactDOM(使用CDN或本地文件均可) wp_enqueue_script('react', 'https://unpkg.com/react@18/umd/react.production.min.js', array(), '18.2.0', true); wp_enqueue_script('react-dom', 'https://unpkg.com/react-dom@18/umd/react-dom.production.min.js', array('react'), '18.2.0', true); // 引入打包后的自定义组件 wp_enqueue_script('react-app-component', get_template_directory_uri() . '/dist/main-xxxx.js', array('react', 'react-dom'), '1.0.0', true); $containerId = 'react-app-' . uniqid(); // 生成唯一ID,避免多实例冲突 ob_start(); ?> <div id="<?php echo $containerId; ?>"></div> <script> // 等待DOM加载完成后再渲染组件 document.addEventListener('DOMContentLoaded', function() { const rootElement = document.getElementById('<?php echo $containerId; ?>'); const message = '<?php echo esc_js($atts['message']); ?>'; // 用React.createElement替代JSX语法 const appElement = React.createElement(window.App, { message: message }); const root = ReactDOM.createRoot(rootElement); root.render(appElement); console.log("代码运行正常"); }); </script> <?php return ob_get_clean(); } add_shortcode('react_app', 'react_app_shortcode');
关键修改说明
- 引入依赖:通过
wp_enqueue_script规范引入React、ReactDOM和自定义组件,确保加载顺序和依赖关系正确。 - 唯一容器ID:用
uniqid()生成容器ID,避免同一页面多个短代码实例的DOM元素冲突。 - DOM加载监听:用
DOMContentLoaded确保组件渲染时目标容器已经存在于DOM中。 - 替代JSX:用
React.createElement将JSX转换为浏览器可识别的原生JavaScript代码。
内容的提问来源于stack exchange,提问作者Sajib Hossain
相关产品推荐
相关产品推荐

