如何在React组件的JSX中正确渲染来自Props的HTML字符串且无警告?
嘿,我来帮你理清这个问题!首先得明确几个关键点:
为什么直接渲染HTML字符串会变成纯文本?
React为了防止XSS攻击,默认会自动转义所有插入JSX的字符串内容。所以你直接写<div>{htmlText}</div>时,HTML标签会被当成普通文本显示,这是React的安全机制在起作用。
关于dangerouslySetInnerHTML的警告
你用dangerouslySetInnerHTML的方式是完全正确的——这是React官方提供的唯一用来渲染原始HTML内容的API。而你看到的ESLint警告react/no-danger,是ESLint在提醒你:这个API有安全风险,必须确保你渲染的HTML内容是完全可信的(比如来自你的后端、经过严格过滤,而不是用户直接输入的内容)。
如果你已经确认内容是安全的,有两种方式可以消除这个警告:
1. 单行为代码添加ESLint忽略注释
直接在使用dangerouslySetInnerHTML的那一行添加注释,告诉ESLint忽略这个规则:
const Item: React.FC<ItemProps> = (props) => { const { item } = props; const { title, htmlText} = item; return ( <div className="item"> <div>{title}</div> {/* 直接渲染纯文本,会转义HTML */} <div>{htmlText}</div> {/* 渲染原始HTML,忽略ESLint警告 */} <div dangerouslySetInnerHTML={{ __html: htmlText }} // eslint-disable-next-line react/no-danger ></div> </div> ) }
2. 封装一个可复用的安全HTML组件
如果你的项目中需要多次渲染可信HTML,可以封装一个专门的组件,在组件内部禁用ESLint规则,这样每次使用时就不用重复加注释了:
// 比如创建一个SafeHTML.tsx组件 type SafeHTMLProps = { html: string; className?: string; }; const SafeHTML: React.FC<SafeHTMLProps> = ({ html, className }) => { return ( <div className={className} dangerouslySetInnerHTML={{ __html: html }} // eslint-disable-next-line react/no-danger /> ); }; export default SafeHTML;
然后在你的Item组件里复用它:
const Item: React.FC<ItemProps> = (props) => { const { item } = props; const { title, htmlText} = item; return ( <div className="item"> <div>{title}</div> <SafeHTML html={htmlText} /> </div> ) }
有没有完全不使用dangerouslySetInnerHTML的方法?
很遗憾,没有。React的设计理念就是默认阻止原始HTML渲染来防范XSS,所以任何渲染原始HTML的方式最终都要依赖dangerouslySetInnerHTML——所谓的“替代方案”本质上都是对这个API的封装。
重要提醒
一定要确保你渲染的HTML内容是可信的!如果HTML来自用户输入或者不可信的第三方,一定要先经过严格的XSS过滤(比如使用DOMPurify库),否则可能会导致恶意脚本注入,引发安全问题。
内容的提问来源于stack exchange,提问作者Lex2000

