首页 > 解决方案 > React markdown - 如何使用 react-markdown 或危险的 SetInnerHTML 获取第 n 个元素并附加另一个元素?

问题描述

我希望在 react html markdown 实现的第二段之后附加一个按钮。我目前正在使用 react-markdown 来编译我的 html 代码。我在这里尝试做的几件事:

  1. 获取 react markdown html 的第 n 个元素(例如:p:2nd-child)
  2. 创建新元素(例如:document.createElement('button'))
  3. 在 (p:2nd-child) 元素之后附加新按钮

我应该使用 ref 来实现这一点,还是像附加纯 JavaScript 一样简单?如果有更好的解决方案,请接受其他建议。

索引.jsx

import React, { useEffect } = 'react'
import ReactMarkdown from 'react-markdown'

const Markdown = (props) => {
  // props.contentHTML seems to be typeof string (with no html tags. 
  //ex: 'hello world' vs '<p>hello world</p>') but converts to appropriate element tags
  const reactHTML = <ReactMarkdown children={props.contentHTML} />

  useEffect(() => {
    // how do i get 2nd element of that reactHTML p tag??
    let secondPElement = ?? reactHTML.querySelector..... ??

    // create element for my button
    let button = document.createElement('button');
    button.id = 'btn-1';
  
    // error here: appendChild does not exist on type 'Element'
    reactHTML.appendChild(button)
  })

  return (
    {reactHTML}
  )

} 

export default Markdown

标签: javascriptreactjsmarkdowndangerouslysetinnerhtmlreact-markdown

解决方案


不幸的是,如果不做一些非正统的事情(阅读:hacky),我认为没有办法实现这一点。

TLDR:这是一个沙盒,我认为对您来说是一个可行的解决方案。

继续,有几个问题阻止您的代码工作。

当您定义时,reactHTML您实际上并不是在定义HTML,而是在定义一个 reactElement 对象(因为 JSX 将它编译成它)。

这意味着您将无法在其上使用 DOM 选择器(例如querySelectorand appendChild),这就是您收到错误消息的原因appendChild does not exist on type 'Element'。这是有道理的,因为 reactElement对象没有这样的方法。

那么,“解决方案”就是像往常一样呈现您的降价内容,并且只有在呈现后才能进入并访问您想要的元素。这可以通过与useEffect您已经在做的非常相似的钩子轻松实现:

const Markdown = (props) => {
  const markdown = `
  This is rendered as a '<p>' element

  So is this one!

  Me too!
  `;

  useEffect(() => {
    // Get all of the <p> elements
    const pElements = document.getElementsByTagName("p");

    // Create a button
    const button = document.createElement("button");
    button.id = "btn-1";
    button.innerHTML = "I'm a button!";

    const refChild = pElements[1];
    // Insert the button before the next sibling of the second <p> tag
    refChild && refChild.parentNode.insertBefore(button, refChild.nextSibling);
  }, []);

  return <ReactMarkdown children={markdown} />;
};

推荐阅读