2

I have a React app using hooks and trying to figure out how to keep a submit button disabled if the search field is empty.

Assuming a regular form field with submit button, how can I set a state hook that keeps the search button disabled until the user inputs text. I assume there should be an onChange function that probably updates the state on input change, but not exactly sure of the implementation.

const [disabled, isDisabled] = useState(true);

<input type="text" id="q" name="q" placeholder="Search.." name="search">
<button type="submit"><i class="fa fa-search"></i></button>
1
  • React's documentation on Controlled components may help on getting the text into state. Commented May 27, 2020 at 20:55

2 Answers 2

9

If you want to disable a button when an input string is empty, then the only state you need is the value of the input string.

const [inputVal, setInputVal] = useState('')

// ...

<input value={inputVal} onChange={e => setInputVal(e.target.value)} />

// ...

<button disabled={!inputVal}> /* ... */ </button>

Here we connect the input component to the state value. This is called a controlled component, because its value is controlled from by an external source (the state value) as opposed to an uncontrolled component, which means the input element holds it's own internal state (the default way inputs work if you don't set their value prop directly.

When the input component receives input (such as someone typing a character) the onChange prop is called. All we do then is take the new value of the input element (e.target.value) and use it to set the state.

If you can derive state from other state, then you shouldn't be storing it in state. Having a state variable called disabled only makes things more complex. The general idea is to use as little state as possible, and compute as much as you can from that state.

Sign up to request clarification or add additional context in comments.

Comments

2

Please check this complete example where I used class component and use a disable property under state object. When you write something on textbox, the disable property will be set as false.

import React from "react";
export default class Login extends React.Component {
    constructor(props) {
        super(props);
        this.state = {disable: true};
    }

    handleChange = (event) => {
        this.setState({disable: event.target.value === ''})
    };

    render() {
        return (
            <div>
                <div>
                    Name: <input onChange={this.handleChange}/> <br/>
                    <button disabled={this.state.disable} >Login</button>
                </div>
            </div>
        );
    }
}

here is the same example of functional component

import React, {useState} from "react";
export default function Login() {

    const [disable, setDisable] = useState(true);

    function handleChange(event) {
        setDisable(event.target.value === '');
    }

    return (
        <div>
            <div>
                Name: <input onChange={handleChange}/> <br/>
                <button disabled={disable}>Login</button>
            </div>
        </div>
    );
}

2 Comments

Why do you need to use class components here? Function components do the job in an easier to understand way. OP even asks how can they do it using hooks.
yes true, I was about to prepare the functional component as well which I already posted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.