I'm looking to append a button after the 2nd paragraph in a react html markdown implementation. I am currently using react-markdown to compile my html code. A few things I am trying to do here:
- Get nth element of the react markdown html (ex: p:2nd-child)
- Create new element (ex: document.createElement('button'))
- Append after the (p:2nd-child) element the new button
Should I use ref to achieve this or is it as simple as appending with plain JavaScript?? Open to other suggestions if there is a better solution.
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
Unfortunately, I don't think there's a way to achieve this without doing something a little unorthodox (read: hacky).
TLDR: Here's a sandbox with what I think is a viable solution for you.
Continuing on, there are a couple of problems preventing your code from working.
When you define
reactHTML
you're not actually defining HTML but rather a reactElement
Object (because that's what JSX compiles it into).This means that you won't be able to use DOM selectors on it (e.g.
querySelector
andappendChild
) and that is why you get the errorappendChild does not exist on type 'Element'
. This makes sense because the reactElement
object does not have such a method.The "solution" then, is to render your markdown content as you normally would, and only after being rendered go in and access the elements that you want. This can be easily achieved with the
useEffect
hook very similar to what you're already doing: