我希望在 React html Markdown 实现的第二段之后添加一个按钮。我目前正在使用react-markdown 来编译我的html 代码。我在这里尝试做的一些事情:
我应该使用 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:这是一个沙箱,我认为这对您来说是一个可行的解决方案。
继续,有几个问题导致您的代码无法工作。
当你定义
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} />;
};
虽然未经测试,但我相信它可以通过
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>