How to disable button in React.js

There are few typical methods how we control components render in React. enter image description here

But, I haven't used any of these in here, I just used the ref's to namespace underlying children to the component.

class AddItem extends React.Component {
    change(e) {
      if ("" != e.target.value) {
        this.button.disabled = false;
      } else {
        this.button.disabled = true;
      }
    }

    add(e) {
      console.log(this.input.value);
      this.input.value = '';
      this.button.disabled = true;
    }

    render() {
        return (
          <div className="add-item">
          <input type="text" className = "add-item__input" ref = {(input) => this.input=input} onChange = {this.change.bind(this)} />
          
          <button className="add-item__button" 
          onClick= {this.add.bind(this)} 
          ref={(button) => this.button=button}>Add
          </button>
          </div>
        );
    }
}

ReactDOM.render(<AddItem / > , document.getElementById('root'));
<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="root"></div>

Using refs is not best practice because it reads the DOM directly, it's better to use React's state instead. Also, your button doesn't change because the component is not re-rendered and stays in its initial state.

You can use setState together with an onChange event listener to render the component again every time the input field changes:

// Input field listens to change, updates React's state and re-renders the component.
<input onChange={e => this.setState({ value: e.target.value })} value={this.state.value} />

// Button is disabled when input state is empty.
<button disabled={!this.state.value} />

Here's a working example:

class AddItem extends React.Component {
  constructor() {
    super();
    this.state = { value: '' };
    this.onChange = this.onChange.bind(this);
    this.add = this.add.bind(this);
  }

  add() {
    this.props.onButtonClick(this.state.value);
    this.setState({ value: '' });
  }

  onChange(e) {
    this.setState({ value: e.target.value });
  }

  render() {
    return (
      <div className="add-item">
        <input
          type="text"
          className="add-item__input"
          value={this.state.value}
          onChange={this.onChange}
          placeholder={this.props.placeholder}
        />
        <button
          disabled={!this.state.value}
          className="add-item__button"
          onClick={this.add}
        >
          Add
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <AddItem placeholder="Value" onButtonClick={v => console.log(v)} />,
  document.getElementById('View')
);
<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='View'></div>

In HTML,

<button disabled/>
<buttton disabled="true">
<buttton disabled="false">
<buttton disabled="21">

All of them boils down to disabled="true" that is because it returns true for a non-empty string. Hence, in order to return false, pass a empty string in a conditional statement like this.input.value?"true":"".

render() {
    return (
        <div className="add-item">
            <input type="text" className="add-item__input" ref={(input) => this.input = input} placeholder={this.props.placeholder} />
            <button disabled={this.input.value?"true":""} className="add-item__button" onClick={this.add.bind(this)}>Add</button>
        </div>
    );
}

Here is a functional component variety using react hooks.

The example code I provided should be generic enough for modification with the specific use-case or for anyone searching "How to disable a button in React" who landed here.

import React, { useState } from "react";

const YourComponent = () => {
  const [isDisabled, setDisabled] = useState(false);
  
  const handleSubmit = () => {
    console.log('Your button was clicked and is now disabled');
    setDisabled(true);
  }

  return (
      <button type="button" onClick={handleSubmit} disabled={isDisabled}>
        Submit
      </button>
  );
}

export default YourComponent;