Bryan Bryan - 15 days ago 5
React JSX Question

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!

Answer

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
  • 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?

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;
    rows[idx].value = e.target.value;
    this.setState({
        rows,
    });
  }
  
  onChecked(idx){
    const rows = this.state.rows;
    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, i) => !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/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"> </div>

Comments