dorkycam
dorkycam

Reputation: 529

Text input unfocused after one character React?

var uuid = require('uuid-v4');
// Generate a new UUID
var myUUID = uuid();
// Validate a UUID as proper V4 format
uuid.isUUID(myUUID);  // true

var questionNum = 0;

class App extends Component {

  constructor(props){
    super(props);
      this.state = {
        key: uuid(),
        title: "",
        author: "",
        questions: [],
        answers: []
      }

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

  handleChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;

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

  addQuestion = () => {
    questionNum++;
    this.setState({
      questions: this.state.questions.concat(["question","hi"])
    });
    console.log(this.state.questions);
    this.setState({
      answers: this.state.answers.concat(["hello","hi"])
    });
    console.log(this.state.answers);
    console.log(questionNum);
    console.log(this.state.title);
    console.log(this.state.author);
  }

  render() {
    return (
      <div className="App">

        <div>
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <h1 className="App-title">Quiz Form 2.0</h1>
          </header>
          <p className="App-intro">
            To get started, edit <code>src/App.js</code> and save to reload.
          </p>
          </div>

        <div>
          <form>
            <div className="Intro">
              Give your Quiz a title: <input type="text" value={this.state.title} onChange={this.handleChange} name="title" key={uuid()}/><br/>
              Who's the Author? <input type="text" value={this.state.author} onChange={this.handleChange} name="author" key={uuid()}/><br/><br/>
            </div>
            <div className="questions">
              Now let's add some questions... <br/>
              {this.addQuestion}
            </div>
          </form>
          <button onClick={this.addQuestion}>Add Question</button>
        </div>

      </div>
    );
  }
}

export default App;

Both of the inputs on my page unfocus after typing only one character. Here's my code, I'm not entirely sure where I am going wrong here, it all worked just fine yesterday.

If there is anything else that you need to know just leave a comment and I will get to it. Your help is much appreciated, thanks!

Upvotes: 3

Views: 10884

Answers (2)

dysfunc
dysfunc

Reputation: 2008

Tholle's response is correct. However, you should make some adjustments to how you interact with state. I've reworked your code with comments and included the uuid fix.

class App extends Component {
  constructor(props){
    super(props);
      this.state = {
        title: "",
        author: "",
        questions: [],
        answers: []
      }

      this.handleChange = this.handleChange.bind(this);
      this.addQuestion = this.addQuestion.bind(this);
  }

  handleChange({ target }) {
    // since you'll always have a synthetic event just destructure the target
    const { checked, name, type, value } = target;
    const val = type === 'checkbox' ? checked : value;

    this.setState({
      [name]: val
    });
  }

  addQuestion() {
    // never modify state directly -> copy state and modify
    const { answers, questions } = Object.assign({}, this.state);
    // update your answers
    answers.push(["hello", "hi"]);
    // update your questions
    questions.push(["question", "hi"]);
    // now update state
    this.setState({
      answers,
      questions
    }, () => {
      console.log(this.state);        
    });
  }

  render() {
    return (
      <div className="App">
        <div>
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <h1 className="App-title">Quiz Form 2.0</h1>
          </header>
          <p className="App-intro">
            To get started, edit <code>src/App.js</code> and save to reload.
          </p>
        </div>

        <div>
          <form>
            <div className="Intro">
              Give your Quiz a title: <input type="text" value={this.state.title} onChange={this.handleChange} name="title" /><br/>
              Who's the Author? <input type="text" value={this.state.author} onChange={this.handleChange} name="author" /><br/><br/>
            </div>
            <div className="questions">
              Now let's add some questions... <br/>
              {this.addQuestion}
            </div>
          </form>
          <button onClick={this.addQuestion}>Add Question</button>
        </div>
      </div>
    );
  }
}

export default App;

Upvotes: 2

Tholle
Tholle

Reputation: 112917

When the key given to a component is changed, the previous one is thrown away and a new component is mounted. You are creating a new key with uuid() every render, so each render a new input component is created.

Remove the key from your inputs and it will work as expected.

<div className="Intro">
  Give your Quiz a title:
  <input
    type="text"
    value={this.state.title}
    onChange={this.handleChange}
    name="title"
  />
  <br/>
  Who's the Author?
  <input
    type="text"
    value={this.state.author}
    onChange={this.handleChange}
    name="author"
  />
  <br/><br/>
</div>

Upvotes: 9

Related Questions