React markdown - 如何获取第 n 个元素并使用 react-markdown 或 dangerouslySetInnerHTML 附加另一个元素?

React markdown - how to get nth-element and append another element using react-markdown or dangerouslySetInnerHTML?

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

  1. 获取反应降价的第 n 个元素 html(例如:p:2nd-child)
  2. 创建新元素(例如:document.createElement('button'))
  3. 在(p:2nd-child)元素后追加新按钮

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

index.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

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

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

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

当你定义 reactHTML 时,你实际上并没有定义 HTML 而是一个反应 Element Object(因为这就是 JSX 将其编译成的内容)。

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

然后,“解决方案”就是像往常一样呈现您的 Markdown 内容,并且只有在呈现后才进入并访问您想要的元素。这可以通过 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} />;
};