如何将ESP32运行时嵌入式变量传入React的App.tsx文件?
解决方案:从ESP32获取LED初始状态并初始化React页面
要实现页面加载时显示LED的真实状态,需要通过ESP32提供API接口返回状态,再在React组件初始化时调用该接口更新本地状态,具体步骤如下:
1. 在ESP32端添加获取LED状态的API接口
首先需要在你的ESP32嵌入式代码中,新增一个HTTP GET接口(比如/api/led-state),用于读取闪存中存储的LED状态并以JSON格式返回。
以ESP-IDF的HTTP服务器为例,核心代码示例:
// 假设你已经有读取闪存LED状态的函数:bool get_led_state_from_flash() esp_err_t get_led_state_handler(httpd_req_t *req) { bool led_state = get_led_state_from_flash(); // 从闪存读取当前LED状态 char response[64]; snprintf(response, sizeof(response), "{\"is_on\": %s}", led_state ? "true" : "false"); httpd_resp_set_type(req, "application/json"); return httpd_resp_send(req, response, HTTPD_RESP_USE_STRLEN); } // 注册接口路由 const httpd_uri_t led_state_uri = { .uri = "/api/led-state", .method = HTTP_GET, .handler = get_led_state_handler, .user_ctx = NULL }; // 在服务器初始化时添加该路由 httpd_register_uri_handler(server, &led_state_uri);
2. 修改React的App.tsx代码,初始化LED状态
在你的React组件中,新增一个获取LED状态的异步函数,并在组件挂载时调用它,更新ledOn的初始值:
修改后的完整App.tsx代码:
import { useState, useEffect} from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import './App.css' function App() { const [btnState, setBtnState] = useState(true); const [message, setMessage] = useState(""); const [ledOn, setLedOn] = useState(false); useEffect(() => { getHelloWorld(); getLedInitialState(); // 新增:获取LED初始状态 webSocket(); }, []); // 新增:获取LED初始状态的函数 const getLedInitialState = async () => { try { const response = await fetch("/api/led-state"); if (!response.ok) throw new Error("Failed to get LED state"); const data = await response.json(); setLedOn(data.is_on); // 更新本地状态为ESP32返回的真实值 } catch (err) { console.error("Error fetching LED state:", err); } }; const getHelloWorld = async () => { const webResult = await fetch("/api/hello-world"); const myText = await webResult.text(); setMessage(myText); }; const getWebSocketUrl = (suffix: string)=>{ const l = window.location; return ((l.protocol == "https:")? "wss://" : "ws://") + l.host + l.pathname + suffix; } const webSocket = () => { const socket = new WebSocket(getWebSocketUrl("ws")) socket.onopen = () => { socket.send("Hello ESP32"); }, socket.onmessage = (event) => { console.log(event.data); try { const AttemptedBtnState = JSON.parse(event.data) setBtnState(AttemptedBtnState.btn_state) }finally{ } } socket.onerror = (err) => console.error(err); socket.onclose = (event) => console.log(event); }; const switchLed = async (is_on: boolean) => { const payload = { is_on } const webResult = await fetch("/api/toggle-led", { method: "POST", body: JSON.stringify(payload), }); if(!webResult.ok) { console.error(webResult.statusText); return; } setLedOn(is_on); }; const getLEDText = () => ledOn? "LED is on" : "LED is off" return ( <> <div> <a href="https://vitejs.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>LearnEsp32</h1> <h1> {message} </h1> <div className="card"> <button style={{background:ledOn? "lightBlue" : "" }} onClick={() => switchLed(!ledOn)}> {getLEDText()} </button> <div style = {{ width: "50px", height: "50px", border: "1px solid black", margin: "auto", borderRadius: "50px", marginTop: "16px", background: btnState? "pink" : "", }}> </div> </div> </> ) } export default App
原理说明
- React作为前端运行在浏览器中,无法直接读取ESP32的闪存数据,必须通过HTTP请求(或WebSocket)与ESP32的网页服务器通信获取数据。
- 组件挂载时(
useEffect的空依赖数组)调用getLedInitialState,从ESP32的API接口获取真实LED状态,再通过setLedOn更新本地状态,页面就会渲染出正确的初始状态。
内容的提问来源于stack exchange,提问作者Barry
相关产品推荐
相关产品推荐

