user6398538
user6398538

Reputation:

State won't change in react

I have an App here that has a child component and I am trying to set the state to whatever the user type something. I also want to track the changes the user is typing.

So far here's what I got:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      firstName: "",
      lastName: "",
      userName: "",
      email: "",
      password: ""
    };

    this._handleChangeInput = this._handleChangeInput.bind(this);
  }

  componentDidMount() {}

  _handleChangeInput(e) {
    this.setState({
      [e.target.name]: e.target.value
    });

    console.log("console log firstName >>>>>>", this.state.firstName);
  }

  render() {
    return (
      <div className="content">
        <SignUp
          formState={this.state}
          _handleChangeInput={this._handleChangeInput}
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));

And here is the child:

import React from "react";

class SignUp extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <form>
          <input
            name="firstName"
            id="firstName"
            placeholder="First Name"
            value={this.props.formState.firstName}
            onChange={e => this.props._handleChangeInput}
          />
        </form>
      </div>
    );
  }
}

export default Form;

Whenever I am trying to type something in the textbox it won't allow me to do so and I don't see anything. What am I doing wrong here? And also how can I track what the user is typing on the textbox via console.log? I was trying to put some console.log inside the componentDidMount but it did not work.

Upvotes: 0

Views: 386

Answers (4)

Jeeva
Jeeva

Reputation: 1590

You can use without e => this.props._handleChangeInput(e) too. You can make the function as below. Get the name and value of your input by destructuring as below.

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      firstName: "",
      lastName: "",
      userName: "",
      email: "",
      password: ""
    };

    this._handleChangeInput = this._handleChangeInput.bind(this);
  }

  _handleChangeInput(e) {
    const { name, value } = e.target;
    this.setState({
      [name]: value
    }, () => {
      console.log("console log firstName >>>>>>", this.state.firstName);
    });
  }

  render() {
    return (
      <div className="content">
        <SignUp
          formState={this.state}
          _handleChangeInput={this._handleChangeInput}
        />
      </div>
    );
  }
}

class SignUp extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <form>
          <input
            name="firstName"
            id="firstName"
            placeholder="First Name"
            value={this.props.formState.firstName}
            onChange={this.props._handleChangeInput}
          />
        </form>
      </div>
    );
  }
}

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

Upvotes: 0

Manoz
Manoz

Reputation: 6617

You can make use of componentWillReceiveProps() here

Pass your whole state

 <div className="content">
    <SignUp formState={this.state} _handleChangeInput={this._handleChangeInput} />
 </div>

Now whenever the state in ParentComponent gets updated, It will get in componentWillReceiveProps() in child component.

Child Component

class SignUp extends React.Component {
  constructor(props) {
    super(props);
  }

  componentWillReceiveProps(props){ // you will receive props here
    this.setState(props.formState);
  }

  render() {
    return (
      <div>
        <form>
          <input
            name="firstName"
            id="firstName"
            placeholder="First Name"
            value={this.state.firstName}
            onChange={e => this.props._handleChangeInput}
          />
        </form>
      </div>
    );
  }
}

Upvotes: 0

The problem here is that your are not controlling input value change on the SignUp component. Look at this sample:

<input type="textarea" value={this.state.relevantInfo} onChange={this.onRelevantInfo_Change}/>

onRelevantInfo_Change = (event) => {
      this.setState({
        relevantInfo: event.target.value
      });
    }

You must also bind the value from state object instead of doing from "props" as you are setting the updated value on the state

Besides, you are passing the full state from parent component to child component this way:

formState={this.state}

You should do it this way, spreading the attributes:

<SignUp {...props} />

Doing this way, it forces to decouple SignUp from its parent component (what you must do anyway), making it reusable.

Summarizing, refactor it to be independent, providing events, getters/setters... to the parent component to get the credentials entered in the sign up form.

Hope it helps.

Upvotes: 0

anttud
anttud

Reputation: 736

You are not passing event on your SignUp class e => this.props._handleChangeInput(e)

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      firstName: "",
      lastName: "",
      userName: "",
      email: "",
      password: ""
    };

    this._handleChangeInput = this._handleChangeInput.bind(this);
  }

  componentDidMount() {}

  _handleChangeInput(e) {
    this.setState({
      [e.target.name]: e.target.value
    }, () => {
      console.log("console log firstName >>>>>>", this.state.firstName);
    });
  }

  render() {
    return (
      <div className="content">
        <SignUp
          formState={this.state}
          _handleChangeInput={this._handleChangeInput}
        />
      </div>
    );
  }
}

class SignUp extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <form>
          <input
            name="firstName"
            id="firstName"
            placeholder="First Name"
            value={this.props.formState.firstName}
            onChange={e => this.props._handleChangeInput(e)}
          />
        </form>
      </div>
    );
  }
}

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

Upvotes: 1

Related Questions