React应用中使用Pyodide调用runPython时出现未定义类型错误
Pyodide在React中运行报错的问题解决
问题描述
引入的Pyodide CDN(index.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <script src="https://cdn.jsdelivr.net/pyodide/v0.21.0/full/pyodide.js"></script> <title>React App</title> </head> <body> <div id="root"></div> </body> </html>
React组件代码(App.js)
import './App.css'; const pythonExec = ()=>{ const python_code = ` print('Hello Test') `; const pyodide = window.pyodide; pyodide.runPython(python_code); }; function App() { return ( <div className="App"> <header className="App-header"> <h1>Search Ticker Name</h1> <button onClick={pythonExec}>Search</button> </header> </div> ); } export default App;
报错信息
App.js:9 Uncaught TypeError: Cannot read properties of undefined (reading 'runPython') at pythonExec (App.js:9:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1) at executeDispatch (react-dom.development.js:9041:1) at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1) at processDispatchQueue (react-dom.development.js:9086:1) at dispatchEventsForPlugins (react-dom.development.js:9097:1) at react-dom.development.js:9288:1
环境版本
- React:
^18.2.0 - React-DOM:
^18.2.0 - Pyodide:v0.21.0
错误原因
未正确初始化Pyodide。Pyodide的CDN脚本加载后不会自动创建window.pyodide实例,必须手动调用异步的loadPyodide()方法完成初始化,等待初始化完成后才能调用Pyodide的API。
解决方案
修改App.js代码,确保Pyodide初始化完成后再执行Python代码:
修改后的App.js代码
import './App.css'; import { useState, useEffect } from 'react'; function App() { const [pyodide, setPyodide] = useState(null); // 组件挂载时初始化Pyodide useEffect(() => { const loadPyodideInstance = async () => { const instance = await window.loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.21.0/full/" }); setPyodide(instance); }; loadPyodideInstance(); }, []); const pythonExec = () => { if (!pyodide) { console.log("Pyodide还在初始化中,请稍等"); return; } const python_code = ` print('Hello Test') `; pyodide.runPython(python_code); }; return ( <div className="App"> <header className="App-header"> <h1>Search Ticker Name</h1> <button onClick={pythonExec} disabled={!pyodide}> {pyodide ? "Search" : "加载Pyodide中..."} </button> </header> </div> ); } export default App;
关键修改点
- 用
useEffect在组件挂载时异步加载Pyodide实例,保存到state中 - 调用
loadPyodide时指定indexURL,确保Pyodide能正确加载依赖文件 - 在执行Python代码前先判断Pyodide是否已初始化,避免报错
- 按钮添加
disabled状态,初始化完成前无法点击,优化用户体验
额外说明
Pyodide的print输出默认会发送到浏览器控制台,可打开开发者工具的Console标签查看内容。
内容的提问来源于stack exchange,提问作者user1470034
相关产品推荐
相关产品推荐

