Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add and Remove HTML Elements on Button Click in React

What's the best uncomplicated way to achieve this jQuery fiddle using just React without using jQuery or any other libraries? I don't quite have the ReactJS skills yet, and was wondering if there was a way to create and delete elements dynamically.

I was thinking of creating a

this.state = { "inputs": ["<input type="text" /><input type="checkbox" />"] }

state variable array that holds the HTML when added, giving each one a unique key based on the index and then .map() it, but am unsure whether there's an easier way to achieve this and am unsure on how to delete each element as such.

Would love any help or feedback, thanks!

like image 963
Bryan Avatar asked Dec 02 '22 14:12

Bryan


2 Answers

Here is a "React" way to do this, I'm not a React expert, so the code could be better, would accept corrections.

  • Yes, react has more boilerplate codes, because you don't handle DOM directly and there is less "magic" which means you have more control overall. (specially as a controlled component)
  • States should be as minimum as possible, you just have to hold the pure data, other decorative stuff let components to handle them.
  • depends on the situation, you may want to separate the Row component into 2 separate components with more props.
  • ??? more suggestions?

UPDATE: after workin with React everyday for the last past 3 years, I found there are some bad practices on the previous code, I have update the code to be cleaner hopefully it helps you.

const Row = function(props){
  const {checked, value, onChange, onChecked} = props;
  return (
    <div>
      <input 
        type="checkbox" 
        checked={checked}
        onChange={onChecked}
        />
      <input type ="text" value={value}  onChange={onChange}/>
    </div>
  );
}

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      rows: [
        {value: 'row1', checked: false},
        {value: 'row2', checked: true},
        {value: 'row3', checked: false},
      ]
    };
  }
  
  updateValue = (e, idx) => {
    const rows = [...this.state.rows];  // copy array because we don't want to mutate the previous one
    rows[idx].value = e.target.value;
    this.setState({
        rows,
    });
  }
  
  onChecked = (idx) => {
    const rows = [...this.state.rows];  // copy array because we don't want to mutate the previous one
    rows[idx].checked = !rows[idx].checked;
    this.setState({
        rows,
    });
  } 
  
  addRow = () => {
    const rows = [...this.state.rows, 
                  {value:'', checked: false}
                 ];
    this.setState({
        rows,
    });
  }
  
  deleteRows = () => {
    this.setState({
      rows: this.state.rows.filter(e => !e.checked)
    });
  }
 
  render(){
    return(
      <div>
        {this.state.rows.map((row, idx) => {
          return(
              <Row 
                key={idx} 
                value={row.value}
                checked={row.checked}
                onChange={(e) => this.updateValue(e, idx)} 
                onChecked={() => this.onChecked(idx)}
                /> 
            )
        })
        }
        <button onClick={this.addRow}>
          add 
        </button>
        <button onClick={this.deleteRows}>
          delete
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.development.js"></script>

<div id="app"> </div>
like image 120
Yichaoz Avatar answered Dec 10 '22 11:12

Yichaoz


Just use the old plain JS way

 var elem = document.getElementById("button_" + id);
 elem.parentNode.removeChild(elem);
like image 29
Martin Tonev Avatar answered Dec 10 '22 10:12

Martin Tonev