Jim
Jim

Reputation: 669

ReactJS: Cannot get the length of a string in component state

I have a little problem. In my function isLoginOk() it never enters into the if. It enters every time in the else even if my string is longer than 1 char.

When I console.log before the if I can see that my string is longer than 1 yet it doesn't go into the if!

Why is that? (I have verified that the string in my component state is correctly updated by handleChange())

export default class InputLogin extends React.Component {
        constructor(props) {
            super(props);
        this.state = {
            login: "",
        }
    };

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

    isLoginOk() {
        if (this.state.login.length > 1) {
            return (<div>OK</div>);
        } else {
            return (<div>ERROR</div>);
        }
    }

    render() {
        return (
            <div>
                <input type="text" name="login" value={this.state.login} onChange={this.handleChange} /> {this.isLoginOk()}
            </div>
        );
    }
}

Upvotes: 2

Views: 11085

Answers (3)

Andy Hoffman
Andy Hoffman

Reputation: 19109

There is a bug in your code, in your handleChange value.

[e.target.name]: [e.target.value]

You're setting the value of this.state.login to ['some input']. Your validation always fails because you can't get the length of the string inside the array using this.state.login.length. Your validation will return either 0 or 1 based on the array length, certainly not what you intended.

To fix this, remove the brackets around [e.target.value].

class InputLogin extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      login: ""
    }
  }
  
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    });
  }
  
  render() {
    const { login } = this.state;
    const loginResult = login.length > 1 ? "OK" : "ERROR";
    
    return (
      <div>
        <input type="text" name="login" value={login} onChange={this.handleChange} />
        {loginResult}
      </div>
    )
  }
}

ReactDOM.render(<InputLogin />, document.querySelector("#app"))
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>


<div id="app"></div>

http://jsfiddle.net/n5u2wwjg/261779/

Upvotes: 1

Dacre Denny
Dacre Denny

Reputation: 30360

It looks like an inconsitency with the way you're setting the component state in handleChange() versus the way isLoginOk() expects the state to be defined.

In the handleChange() function, the "square bracket" syntax [e.target.value] means that you're setting the state value for key [e.target.name] as an array:

 this.setState({
        // Brackets around [e.target.value] creates array value
        [e.target.name]: [e.target.value] 
 });

The isLoginOk() function however, expects the value to be a string rather than an array:

isLoginOk() {

    // You're accessing the string directly and not as an array item
    if (this.state.login.length > 1) {
        return (<div>OK</div>);
    } else {
        return (<div>ERROR</div>);
    }
}

Consider revising your handleChange() function like so to ensure that the state is updated in a way that is compatible with isLoginOK():

handleChange = (e) => {
    this.setState({
        [e.target.name]: e.target.value // Remove the [ and ] around value
    });
}

Upvotes: 3

varoons
varoons

Reputation: 3887

Remove the brackets around e.target.value

Also simplify the render and get rid of the isLoginOk function. Seems unnecessary.

<input type="text" name="login" value={this.state.login} onChange={this.handleChange} /> 
<div>{ this.state.login.length > 1 ? 'OK' : 'ERROR' }</div>

Upvotes: 0

Related Questions