React组件中{this.state.number}输出带引号字符串的原因及解决办法
React渲染HTML字符串显示为带引号文本的原因及解决办法
问题原因
- React的自动转义机制:React默认会转义所有渲染的字符串内容,目的是防止XSS注入攻击。你直接把HTML字符串赋值给state后渲染,React会将整个字符串(包括
<tr>这类标签)当成普通文本输出,所以会显示带引号的完整字符串内容。 - 模板字符串语法错误:你用单引号
'包裹HTML片段,里面的{ele.name}不会被解析成变量值,只会作为普通字符串拼接进去。 - 不必要的多次状态更新:在
forEach循环里多次调用setState,会导致组件频繁重渲染,既影响性能也不符合逻辑。
解决办法
方法一:使用dangerouslySetInnerHTML(不推荐,仅限安全内容)
React提供dangerouslySetInnerHTML属性直接渲染HTML字符串,但存在XSS风险,仅当你完全信任内容来源时使用。
修改要点:
- 把字符串拼接的单引号改成反引号
`,让${ele.name}能被正确解析 - 将
setState移到forEach循环外,只更新一次状态 - 渲染时用
dangerouslySetInnerHTML替代直接输出字符串
// 修改componentDidMount部分 async componentDidMount() { let tokensvar = `<tr> <td>1</td> <td>2</td> </tr>`; const url = "https://api.multiversx.com/accounts/erd1n0kgesdn7hc63amdfygqfdj9enfa07n2hwup9y8732fg35qcug8q0w0x8s/tokens"; const response = await fetch(url); const data = await response.json(); data.forEach((ele) =>{ tokensvar += `<tr> <td>${ele.name}</td> <td>${ele.name}</td> </tr>`; }) this.setState({ number: tokensvar, loading: false }); } // 修改render部分 render() { // ... 省略loading和空状态判断 return ( <div> <table className="Token-section-output" dangerouslySetInnerHTML={{ __html: this.state.number }} /> </div> ); }
方法二:使用React元素数组(推荐,符合最佳实践)
React的核心是用元素描述UI,而非拼接HTML字符串。直接将接口数据转换成React元素数组渲染,既安全又易维护。
完整修改代码:
import React from "react"; export default class Tokens extends React.Component { state = { loading: true, tokens: [] // 存储原始数据,而非HTML字符串 }; async componentDidMount() { const url = "https://api.multiversx.com/accounts/erd1n0kgesdn7hc63amdfygqfdj9enfa07n2hwup9y8732fg35qcug8q0w0x8s/tokens"; try { const response = await fetch(url); const data = await response.json(); this.setState({ tokens: data, loading: false }); } catch (error) { console.error("获取数据失败:", error); this.setState({ loading: false }); } } render() { if (this.state.loading) { return <div>loading...</div>; } if (this.state.tokens.length === 0) { return <div>没有获取到token数据</div>; } return ( <div> <table className="Token-section-output"> <thead> <tr> <th>名称</th> <th>名称</th> </tr> </thead> <tbody> {/* 初始固定行 */} <tr> <td>1</td> <td>2</td> </tr> {/* 遍历数据生成React元素 */} {this.state.tokens.map((ele, ind) => ( <tr key={ind}> {/* 建议使用唯一ID作为key,这里临时用索引 */} <td>{ele.name}</td> <td>{ele.name}</td> </tr> ))} </tbody> </table> </div> ); } }
该方法优势:
- 彻底避免XSS风险,React自动处理内容转义
- 代码更易读、易调试,符合React组件化思想
- 仅更新一次状态,避免不必要的重渲染
内容的提问来源于stack exchange,提问作者August 7337
相关产品推荐
相关产品推荐

