-2

I'm creating a page that if user clicks add more button a text box should be added as many time the user clicks

I have created a component where I've created texbox. I've tried to render this component into another component on button click but it is not working. why?


class Addmore extends React.Component {
  render() {
    return (
      <div>
        <label className="float-left"> CC</label>
        <input type="text" class="form-control" />
      </div>
    );
  }
}

class abc extends React.Component {
    constructor(props)
    {
        super(props);
    }
  state = {
    addcomp: false
  };

  click() {
    this.setState({
        addcomp: true,
      });
     var x= document.getElementById("more");
     x.parentNode.appendChild(<Add/>);
  }
  render() {
    return (
            <div class="row">
            <div class="col-3">
            <label className="float-left"> BU</label>
             <input type="text" class="form-control" />


             <div id="more">

              //HERE I HAVE TO RENDER ADDMORE
                         COMPONENT

             </div>

             <div class="col-3">
                  <button type="button" onClick={this.click.bind()}>
                                Add more
                  </button>
             </div>
    );
  }
}
export default abc;
vsync
  • 118,978
  • 58
  • 307
  • 400
vicky
  • 5
  • 1
  • 4
  • `this.click.bind(this)` - The `bind()` method needs a context parameter. Read MDN. – vsync Aug 12 '19 at 07:25
  • You must not use `appendChild` and `getElementById` in React. You modify the DOM vaie props change and not directly. React handles the DOM changes itself. – vsync Aug 12 '19 at 07:27
  • `var x= document.getElementById("more");` - it's not a react approach, instead create another component – uladzimir Aug 12 '19 at 07:28

1 Answers1

3

You should let React render everything, and your job is only to tell React what to render and, in your case, how many times.

For that, a counter can be used to track how many dynamically-added elements should be "injected" inside the <Example> component.


A mindshift is needed here, since in your example you are coming from a place where you think that the click handler itself should modify the DOM, and in React that is an antipattern.


You should work with the React state, and that means the click handler should update the state of the host component which will trigger a re-render (this is how React works) and in the next render cycle, your added component will be rendered as many times as the counter value, because that counter change is what triggered the re-rendering.

In React, the props & state are the way to trigger re-render and any DOM modification should be done by changing the internal component's state, or by sending different props, from the parent component.


In the below example I do not use Classes, but use Hooks instead, because I've stopped using class altogether once hooks were released, because I think it's cleaner:

// Get a hook function
const {useState, useCallback} = React;

// The added element component
const AddedElement = () => <div><input placeholder='text box' /></div>

// The "app" component
const Example = () => {
  const [count, setCount] = useState(0);

  return <div>
    <button onClick={() => setCount(count + 1)}>
      Click me
    </button>
    { Array(count).fill(<AddedElement />) }
  </div>
};

// Render 
ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

If you are interested in how to repeatedly render the same component, I've written an answer about this in this question: How can I render repeating React elements?

vsync
  • 118,978
  • 58
  • 307
  • 400