javascripthtmlreactjsreact-nativesurveyjs

Append Element to an Existing Element React


I'm creating a survey with SurveyJs. In doing so, I'm looking to create a button to add to every question title. I've been able to do the following with Javascript but I'm looking to essentially do the same thing with React.

Rendering the survey works fine so I don't think it's worth showing that. The following is the callback function when every question is rendered. The following works fine:

const onAfterRenderQuestion = (survey, options) = {
  // create the button
  const btn = document.createElement("button")
  btn.innerHTML = "Click me!"

  // define what the button should do
  btn.onClick = function () {
    // do whatever
  }

  // get the question title from the survey and append the button to the end of it
  let header = options.htmlElement.querySelector("h5")
  if (!header) header = options.htmlElement
  header.appendChild(btn)
}

The above code works fine and as you can see, it is using Javascript. However, I'm trying to do the exact same thing using React but I'm not able to do so. For now, I've got this:

// create the button component
const myButtonElement = (
  <Button onClick={() => {*call some function*}}
)    

let header = options.htmlElement.querySelector("h5")
if (!header) header = options.htmlElement

// create the entire component
const questionTitle = React.createElement("div", {}, header)
const buttonElement = React.createElement("div", {}, myButtonElement)

const titleWithButton = React.createElement("div", {}, [questionTitle, buttonElement])

ReactDOM.render(titleWithButton, document.getElementById(options.question.id))

However the above code results in the following error:

Error: Objects are not valid as a React child (found: [object HTMLHeadingElement]). If you meant to render a collection of children, use an array instead.

Even if one is not familiar with Surveyjs, how can I simply append an element to an existing element using React, similar to how I've already done it with Javascript?


Solution

  • It's because the header is an HTML element whereas react expects the third argument to be a react element.

      let header = options.htmlElement.querySelector("h5")
      if (!header) header = options.htmlElement
    
      const questionTitle = React.createElement("div", dangerouslySetInnerHTML: {__html: `<h5>${header.innerHTML}</h5>` })
    

    HTML written inside JSX isn't native HTML components. These are developed by react team to mimic HTML and is react component.