You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将从PostgreSQL获取的内容渲染为React JSX而非字符串?

解决React渲染HTML字符串为普通文本的问题

问题分析

  1. React默认会转义所有字符串内容,直接渲染HTML字符串会被当作普通文本显示,无法解析为HTML元素。
  2. 父组件存在异步更新时机问题:dispatch更新Redux Store是异步操作,finally块执行时article可能还未从Store中更新,导致setFile设置的是旧值。

解决方案

步骤1:修正父组件的数据更新逻辑

用useEffect监听article的变化,确保file能拿到最新内容,替代原finally块的逻辑:

const ArticleCnt = () => {  
  const dispatch = useDispatch()
  const { article } = useSelector(s => s.articleContent);
  const [file, setFile] = useState("");
  const location = useLocation();

  // 发起请求获取文章数据
  useEffect(() => {
    axios.get("http://localhost:2003/article", {
      params: {
        id: location.pathname.split("/")[1]
      }
    })
    .then(({ data }) => {
      dispatch(setArticleContentTo(data))
    })
    .catch((err) => console.log("Error Occured Here: ", err.message))
  }, [dispatch, location.pathname]);

  // 监听article变化,更新本地state
  useEffect(() => {
    if (article) {
      setFile(article);
    }
  }, [article]);

  const containerVariants = {
    hidden: { x: "100vw" },
    visible: { x: 0, transition: { duration: .6 } },
    exit: { x: '-100vw', transition: { duration: .6, delay: 2 } }
  } 

  return (
    <motion.div className="app-main" variants={containerVariants} exit="exit" initial="hidden" animate="visible">
      <ArticlePanel />
      <div className="app-container">
        <ArticleHeader />
        <ArticleThumbnail />
        <ArticleInfo />
        <div className="app-article-cnt">
          <ArticleContent articleFile={file} />
          <ArticleComment /> 
        </div>
      </div>
    </motion.div> 
  );
}

步骤2:子组件用dangerouslySetInnerHTML渲染HTML

React提供dangerouslySetInnerHTML属性解析HTML字符串,同时建议对内容做XSS过滤保障安全:

// 可选但推荐安装dompurify过滤恶意内容:npm install dompurify
import DOMPurify from 'dompurify';

const ArticleContent = ({ articleFile }) => {
  const [isPending, setIsPending] = useState(true); 

  useEffect(() => {
    setIsPending(!articleFile);
  }, [articleFile]); 

  // 清理HTML中的恶意脚本
  const sanitizedContent = DOMPurify.sanitize(articleFile);

  return ( 
    <div className="app-article-content">
      {isPending ? (
        <>
          <div>
            <h1><Skeleton /></h1>
            <Skeleton count={50} /> 
          </div>
        </>
      ) : (
        <div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
      )}
    </div>
  );
}

注意事项

  • dangerouslySetInnerHTML的命名是为了提醒开发者:直接渲染未过滤的HTML存在XSS攻击风险,必须对用户提供的内容进行过滤。
  • dompurify能有效清理HTML中的恶意脚本,大幅提升应用安全性。

内容的提问来源于stack exchange,提问作者Chinedu Fabian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:25:13