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

问题描述 投票:0回答:2

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

  1. 获取 React Markdown html 的第 n 个元素(例如: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
javascript reactjs markdown dangerouslysetinnerhtml react-markdown
2个回答
1
投票

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

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

继续,有几个问题导致您的代码无法工作。

当你定义

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

这意味着您将无法在其上使用 DOM 选择器(例如

querySelector
appendChild
),这就是您收到错误
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} />;
};

0
投票

虽然未经测试,但我相信它可以通过

components
道具来完成,比如

<Markdown
  components={{
    p(props) {
      const { node, ...rest } = props;
      return (
        <>
          <p {...rest} />
          <button id="btn-1">ImaButton!</button>
        </>;
      );
    },
  }}
>
  # Hello, world!
  This is a paragraph.
</Markdown>
© www.soinside.com 2019 - 2024. All rights reserved.