0

I am simply trying to get the text from the input field for which handler function is attached to a button and then just trying to store in input value into the state object.
But the state object doesn't store that value

class EditTextArea extends React.Component {
    constructor() {
        super();
        this.state = {
            message: "",
        };
        this.handleButton = this.handleButton.bind(this);
    }

    handleButton(e) {
        const text = e.target.previousElementSibling.value;
        this.setState({ message: text });
        console.log(this.state);
    }

    render() {
        return (
            <div>
                <form>
                    <input type="text" name="customText" />
                    <button type="button" onClick={this.handleButton}>
                        Send
                    </button>
                </form>
            </div>
        );
    }
}

ReactDOM.render(<EditTextArea />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
Premlatha
  • 1,676
  • 2
  • 20
  • 40

4 Answers4

3

Nothing in your render is using this.state.message, so you're not going to see anything happen. (Note that if you're wondering about the console.log of state, see this question's answers; the update is asynchronous.)

If you actually use message, you see that it works:

class EditTextArea extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            message: "",
        };
        this.handleButton = this.handleButton.bind(this);
    }

    handleButton(e) {
        const text = e.target.previousElementSibling.value;
        this.setState({ message: text });
    }

    render() {
        return (
            <div>
                <div>
                Message is: {this.state.message}
                </div>
                <form>
                    <input type="text" name="customText" />
                    <button type="button" onClick={this.handleButton}>
                        Send
                    </button>
                </form>
            </div>
        );
    }
}

ReactDOM.render(<EditTextArea />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

Also note that you need to accept a parameter in your constructor and pass it to super(); see above. That wasn't the problem, but it still still incorrect.

That said, I wouldn't do it that way. If you want an uncontrolled input, use a ref to access its value so you don't have to do the DOM traversal, which is easily broken with a small change to render:

class EditTextArea extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            message: "",
        };
        this.handleButton = this.handleButton.bind(this);
        this.inputRef = React.createRef(null);
    }

    handleButton() {
        const text = this.inputRef.current.value;
        this.setState({ message: text });
    }

    render() {
        return (
            <div>
                <div>
                Message is: {this.state.message}
                </div>
                <form>
                    <input type="text" name="customText" ref={this.inputRef} />
                    <button type="button" onClick={this.handleButton}>
                        Send
                    </button>
                </form>
            </div>
        );
    }
}

ReactDOM.render(<EditTextArea />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

Or you might consider a controlled component.

More about controlled vs. uncontrolled components hrere. More about refs here.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks a lot buddy, for giving such a nice solution. And using that ref is really a good idea I am also thinking of a better solution for that. – Shubham Maheshwari Apr 21 '21 at 02:07
2

I run your script so initially, your message state taking an empty state just add a text and click a couple of times so Your message state is updating the second time. So if you need to dynamic change on input so I suggest you right an input handler and call it into the input change function and handle it separately.

 onInputchange(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }
Bilal khan
  • 31
  • 4
0

I tried your code and it actually worked. But the problem is you cant change state and get changed state in same function, it reads the previus state. Just try to click button 2 times, you will see it works

Hypér
  • 124
  • 2
  • 6
  • 1
    **If** this is what they're asking about (and you may be right), we have a [canonical duplicate for it](https://stackoverflow.com/questions/41446560/react-setstate-not-updating-state). – T.J. Crowder Apr 20 '21 at 18:14
  • Yes, I think he only clicked one time and he saw the old state. His problem probably is trying to get the changed state after the use setState, in same function. And yes your link is the solution of this problem – Hypér Apr 20 '21 at 18:32
  • (The point is that if you think this is the problem they're asking about, instead of *answering*, you'd vote to close as a duplicate and post a comment. This is SO's model to avoid having a zillion different questions all with essentially the same answers.) – T.J. Crowder Apr 20 '21 at 18:43
  • Yes you are right but If he is new on this it may not solve this or it may take so much time. Why should I vote for close this post instead of help him? He can close his own post after that.(I don't know am I right about helping for basic or obtainable things. Maybe he should search by himself and improve his searchs.) – Hypér Apr 21 '21 at 07:32
  • Because that's how StackOverflow works, part of the success of its model. Posting answers to duplicate questions that just cover the same ground as previous answers to the earlier questions is actively harmful to the site. – T.J. Crowder Apr 21 '21 at 07:34
0

In react states are updated asynchronously. To check your updated state you can check it by logging in render or in react developer tools.

According to you code you can check code given below

class EditTextArea extends React.Component {
    constructor() {
        super();
        this.state = {
            message: "",
        };
        this.handleButton = this.handleButton.bind(this);
    }

    handleButton(e) {
        const text = e.target.previousElementSibling.value;
        this.setState({ message: text });
        console.log(this.state);//It will show you old value
    }

    render() {
    console.log("check your updated state",this.state)
        return (
            <div>
                <form>
                    <input type="text" name="customText" />
                    <button type="button" onClick={this.handleButton}>
                        Send
                    </button>
                </form>
            </div>
        );
    }
}
avanish
  • 77
  • 1
  • 3