I want to change the state on click of a button in React. Essentially I am trying to update the value of the name displayed in my div by setting this.state.name equal to whatever is typed in the text-box.

What am I doing wrong here?

I also don't quite understand the difference between onClick={() => this.updateText()} and onClick={this.updateText()} and/or onClick={this.updateText}. Maybe it's related to that?

Form.tsx

import React from 'react';

export default class Form extends React.Component<any, any> {

  constructor(props: any) {
    super(props);

    this.state = {
      title: "Enter a new name here",
      description: "Hola",
      textInput: null,
      name: this.props.name
    };
  }

  updateText() {
    this.setState({
      name: this.state.textInput
    });
  }

  render() {
    return (
      <div className="App">
        <div>{this.props.text} {this.state.name}</div>
        <div>{this.state.age}</div>
        <input type="text" placeholder={this.state.title}>{this.state.textInput}</input>
        <br />
        <button type="submit" onClick={() => this.updateText()}>Submit</button>
      </div>
    );
  }
}

App.tsx

import React from 'react';
import './App.css';
import Form from "./Form";

class App extends React.Component {
  render() {
    return (
      <div className="App">
        <Form text="Hello" age={22} name="Thomas"/> 
      </div>
    );
  }
}

export default App;

this.state.name comes up as empty or null upon typing something and clicking the submit button.

1 Answers

0
devserkan On Best Solutions

As @Alexander Staroselsky said in his comment, you should use an onChange handler for your input. This way you can update the textInput and set it to your name value.

{this.updateText()} is not a proper way of using the handler. If you use it like that it is invoked on every render but not with the click.

onClick={this.updateText} Here, you can use the function reference and it works. But, either you have to bind it in the constructor or define it as an arrow function. You can see an example below.

onClick={() => this.updateText()} This is an option of using it. You are using here an arrow function for your handler. It works also without binding your handler function for this. But, with this way your handler function is recreated with every render. Avoid this if possible.

class App extends React.Component {
  render() {
    return (
      <div className="App">
        <Form text="Hello" age={22} name="Thomas"/> 
      </div>
    );
  }
}

class Form extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      title: "Enter a new name here",
      description: "Hola",
      textInput: "",
      name: this.props.name
    };
  }

  updateText = () => {
    this.setState({
      name: this.state.textInput
    });
  }

  handleChange = (e) => this.setState({ textInput: e.target.value})

  render() {
    return (
      <div className="App">
        <div>{this.props.text} {this.state.name}</div>
        <div>{this.state.age}</div>
        <input value={this.state.textInput} onChange={this.handleChange} type="text" placeholder={this.state.title} />
        <br />
        <button type="submit" onClick={this.updateText}>Submit</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />