React使用dangerouslySetInnerHTML渲染HTML仅显示"}"的解决方法
问题根因定位
你当前的代码出现渲染异常,核心是两个逻辑错位:
dangerouslySetInnerHTML要求传入同步可访问、结构严格为{ __html: 有效HTML字符串 }的对象,但你在JSX里直接调用的getData()是个异步函数:函数内部发起的axios请求不会阻塞函数执行,整个getData调用完返回的是undefined,根本拿不到你在.then日志里打印的HTML字符串。你在.then回调里return的{__html: ...}属于Promise链的返回值,和外层的getData函数没有返回关联。- 你的代码里引入了
useState但完全没有使用,异步拿到的HTML字符串没有触发组件状态更新,哪怕数据成功获取,也不会重渲染到页面上。页面出现零散的}符号,是渲染阶段属性值结构异常、加上你JSX里div闭合标签后多写的分号被当作普通文本渲染共同导致的。
正确实现方式
这类需要异步拉取内容再渲染的场景,标准流程是:
- 用组件状态存储最终要传入
dangerouslySetInnerHTML的结构化对象,给一个符合要求的初始值(避免属性值为undefined触发异常) - 在组件挂载的副作用钩子(
useEffect)中发起数据请求,拿到HTML字符串后更新状态,触发组件重渲染 - 将状态中保存好的、结构正确的对象绑定到
dangerouslySetInnerHTML属性上
修正后的可运行代码:
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { // 初始化状态,结构完全匹配dangerouslySetInnerHTML的要求 const [htmlConfig, setHtmlConfig] = useState({ __html: '' }); // 组件挂载后发起一次数据请求,避免在渲染逻辑中重复请求 useEffect(() => { axios .get('/api/data') .then((response) => { const newDataHTML = response.data[0].rule; // 更新状态,把拿到的字符串包装成要求的结构 setHtmlConfig({ __html: newDataHTML }); }) .catch(err => console.log(err)); }, []); // 空依赖数组保证请求只在组件首次挂载时执行 return ( <div className="App"> <Tabs defaultTab="data" onChange={(tabId) => { console.log(tabId) }}> <TabList> <Tab tabFor="data">New Data</Tab> </TabList> <TabPanel tabId="data"> <div dangerouslySetInnerHTML={htmlConfig}></div> </TabPanel> </Tabs> </div> ); } export default App;
使用注意事项
- 这个属性名称里的
dangerously是官方明确的安全提示:如果插入的HTML是用户可控、未经过滤的内容,很容易引发XSS注入风险,一定要确保内容来源可信,必要时对HTML字符串做安全消毒。 - 给
dangerouslySetInnerHTML传值时,不要在对应div标签内同时写其他子节点,也不要在标签后加多余的标点符号,否则会被解析为页面文本。 - 不要把异步请求的返回值直接绑定到JSX属性上,所有异步拿到的动态内容,必须通过状态更新同步到渲染流程中,否则永远拿不到预期的结果。
内容的提问来源于stack exchange,提问作者coding cat
相关产品推荐
相关产品推荐

