简体   繁体   中英

Add onclick or eventListener in insertAdjacentHTML in react-js

I am building a simple react app for learning purpose, I just started learning react-js, I was trying to add paragraph dynamically on user action and it worked perfectly But I want to add an onClick event in insertAdjacentHTML (basically innerHTML).

But onclick event is not working in innerHTML

app.js

const addParagraph = () => {
    var paragraphSpace = document.getElementById('container')
    paragraphSpace.insertAdjacentHTML('beforeend', `<p>I am dynamically created paragraph for showing purpose<p> <span id="delete-para" onClick={deleteParagraph(this)}>Delete</span>`
}

const deleteParagraph = (e) => {
    document.querySelector(e).parent('div').remove();
}

class App extends React.Component {
    render() {
        return (
            <div>
                <div onClick={addParagraph}>
                     Click here to Add Paragraph
                </div>

                <div id="container"></div>
            </div>
        )
    }
}

What I am trying to do?

User will be able to add multiple paragraphs and I am trying to add a delete button on every paragraph so user can delete particular paragraph

I have also tried with eventListener like:-

const deleteParagraph = () => {
    document.querySelector('#delete').addEventListener("click", "#delete", 
    function(e) {
          e.preventDefault();
          document.querySelector(this).parent('div').remove();
        })
}

But It said

deleteParagraph is not defined

I also tried to wrap deleteParagraph in componentDidMount() But it removes everything from the window.

Any help would be much Appreciated. Thank You.

insertAdjecentHTML should not be used in javascripts frameworks because they work on entirely different paradigm. React components are rerendered every time you change a component state. So you want to manipulate look of your component by changing its state

Solution: In constructor initialize your component's state which you will change later on button click. Initial state is array of empty paragraphs.

constructor() {
    super()
    this.state = {
      paragraphs:[]
    }
  }

And alter that state on button click - like this:

<div onClick={addParagraph}>

Add Paragraph function

const addParagraph = () =>{
   this.state = this.state.push('New paragraph')
}

Rendering paragraphs

<div id="container">
this.state.paragraphs.map(paragraph =>{
   <p>{paragraph}</p>
})
</div>

Additional tip for ReactJS in 2022 - use Functional components instead of Class components

Do not manipulate the DOM directly, let React handle DOM changes instead. Here's one way to implement it properly.

class App extends React.Component {
  state = { paragraphs: [] };

  addParagraph = () => {
    // do not mutate the state directly, make a clone
    const newParagraphs = this.state.paragraphs.slice(0);

    // and mutate the clone, add a new paragraph
    newParagraphs.push('I am dynamically created paragraph for showing purpose');

    // then update the paragraphs in the state
    this.setState({ paragraphs: newParagraphs });
  };

  deleteParagraph = (index) => () => {
    // do not mutate the state directly, make a clone
    const newParagraphs = this.state.paragraphs.slice(0);

    // and mutate the clone, delete the current paragraph
    newParagraphs.splice(index, 1);

    // then update the paragraphs in the state
    this.setState({ paragraphs: newParagraphs });
  };

  render() {
    return (
      <div>
        <div onClick={this.addParagraph}>Click here to Add Paragraph</div>
        <div id="container">
          {this.state.paragraphs.map((paragraph, index) => (
            <>
              <p>{paragraph}</p>
              <span onClick={this.deleteParagraph(index)}>Delete</span>
            </>
          ))}
        </div>
      </div>
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM