2

I have multiple text input fields and a single checkbox. Whenever I check the checkbox, I want to clear one of my text input fields. I looked at various answers for this, however, none of them worked.

Here is my code:

import React, { Component } from 'react';

class Form extends Component {
    state = {}

    constructor(props) {
        super(props);
        this.state = {
            text1: "",
            text2: ""
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleClear = this.handleClear.bind(this);
      }

      handleChange(event) {
        let name = event.target.name;
        let value = event.target.value;
        this.setState({[name]: value});
      }

      handleClear(event){
        let checked = event.target.checked;
        if(checked){
            this.setState({"text2": ''}); // did not work
            // how to do it???
            console.log(this.state)
        }
      }

    render() { 
        return (
            <form>
                <input type="text" name="text1" onChange={this.handleChange}/>
                <input type="text" name="text2" onChange={this.handleChange}/>
                <input type="checkbox" name="clear-text2" onChange={this.handleClear}/>
            </form>
        );
    }
}
 
export default Form;

In this code, I want the field text2 to get cleared when the checkbox is checked.

2
  • setState is asynchronous so you can't see if the state was changed immediately after the change. Commented Jul 5, 2020 at 12:19
  • @D10S So, how to do it instantly?. But even after changing the state, input is not getting cleared! What am I missing? Commented Jul 5, 2020 at 12:31

2 Answers 2

4

Your text inputs are not controlled components, they have an onChange but you did not set a value property:

class Form extends React.Component {
  state = {};

  constructor(props) {
    super(props);
    this.state = {
      text1: '',
      text2: '',
    };
    //remove bind, using arrow functions will bind
  }

  handleChange = (event) => {//arrow function
    let name = event.target.name;
    let value = event.target.value;
    this.setState({ [name]: value });
  };

  handleClear = (event) => {//arrow function
    let checked = event.target.checked;
    if (checked) {
      this.setState({ text2: '' }, () =>
        //log in the setState callback gets the current state
        //  you do not want to nest this too much, you already
        //  know the state because you just set it so there is
        //  usually no need for this
        console.log('works:', this.state)
      );

      console.log('does not work', this.state);
    }
  };

  render() {
    return (
      <form>
        <input
          type="text"
          name="text1"
          value={this.state.text1}
          onChange={this.handleChange}
        />
        <input
          type="text"
          name="text2"
          // added value property to text2
          value={this.state.text2}
          onChange={this.handleChange}
        />
        <input
          type="checkbox"
          name="clear-text2"
          onChange={this.handleClear}
        />
      </form>
    );
  }
}

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

here is a functional component example:

const Form = () => {
  //using useState to set state
  const [state, setState] = React.useState({
    text1: '',
    text2: '',
  });
  //using useCallback for event handlers
  const handleChange = React.useCallback((event) => {
    let name = event.target.name;
    let value = event.target.value;
    //pass callback to setState to get current state
    //  and copying state to new state
    setState((state) => ({ ...state, [name]: value }));
  }, []);

  const handleClear = React.useCallback((event) => {
    let checked = event.target.checked;
    if (checked) {
      setState((state) => {
        const newState = { ...state, text2: '' };
        console.log('works', newState);
        return newState;
      });
      //logging a stale closure will not work
      //  and only creates needless dependency
      // console.log('does not work', state);
    }
  }, []);
  //no this in jsx
  return (
    <form>
      <input
        type="text"
        name="text1"
        onChange={handleChange}
      />
      <input
        type="text"
        name="text2"
        // added value property to text2
        value={state.text2}
        onChange={handleChange}
      />
      <input
        type="checkbox"
        name="clear-text2"
        onChange={handleClear}
      />
    </form>
  );
};

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

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

7 Comments

Could you share the same problem doing functional components using hooks!
@Momin Added functional component example.
Thanks! Suppose I only want to apply functional components for my whole projects, is it possible, or is it a right approach?
@Momin Yes, it's fine to only use functional components in react applications.
@Momin this redux book is a bit old as it still uses connect but does explain redux quite well. And read the react guide.
|
3

Try this somthing like this,

<input type="text" name="text1" onChange={this.handleChange} value={this.state.text1} />
<input type="text" name="text2" onChange={this.handleChange} value={this.state.text2} />

You are not passing the state value to input elements. So, value defaults to null So React is letting you mod that input. And your mistakenly thinking your state has control of the input value.

Comments

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.