admin管理员组

文章数量:1431253

Once I started passing props from parent to child to child I have been getting this problem where the getQuestion function only gets me the first letter typed, In addition in the input field nothing shows up.

Before when my code was just Parent to child it worked.

I want to know what exactly is going on because I have tried debugging by console logging and all I know is certain is that it only registers the first letter.

This question did not help because I have not misspelled onChange.

Can't type in React input text field

App.js

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



    this.getPostId = this.getPostId.bind(this);
    this.getQuestion = this.getQuestion.bind(this);
    this.makePost = this.makePost.bind(this);
    this.getBody = this.getBody.bind(this);
    this.getPostType = this.getPostType.bind(this);
    this.getImgSrc = this.getImgSrc.bind(this);
    this.submitPost = this.submitPost.bind(this);
    this.formOpen = this.formOpen.bind(this);
    this.formClose = this.formClose.bind(this);

    this.back = this.back.bind(this);
    this.showPost = this.showPost.bind(this);
    this.renderPosts = this.renderPosts.bind(this);

    //Answer/Response methods
    this.makeAnswer = this.makeAnswer.bind(this);
    this.getAnswer = this.getAnswer.bind(this);
    this.submitAnswer = this.submitAnswer.bind(this);

    this.state = {
      posts: [],

        answers: [],

      question: '',
      body: '',
      postType: 'Question',
      imgSrc: '',
      form: false,
      openedPost: null,
      answer: '',
      favorited: false,

      //sign up
      email:'',
      password: '',
      user: null

    }

}
getQuestion(event) {
  event.preventDefault();
  this.setState({ question:event.target.value });
}


render() {


    return (

      <Router>
        <div className="container">
          <Route
                  exact path={"/"}
                  ponent={() => <Home />}
          />

          <Route
                  exact path={"/home"}
                  ponent={() => <Home />}
          />

          <Route
                exact path={"/signup"}
                ponent={() => <SignUp />}
          />

          <Route
                exact path={`/dashboard`}
                ponent={() =>
                  <Dashboard back={this.back}
                    form={this.state.form}
                      openedPost={this.state.openedPost}
                        renderPosts={this.renderPosts}
                          formClose={this.formClose}
                            formOpen={this.formOpen}
                              posts={this.state.posts}
                                getPostId={this.getPostId}
                                  getQuestion={this.getQuestion}
                                    makePost={this.makePost}
                                      getBody={this.getBody}
                                        getPostType={this.getPostType}
                                          getImgSrc={this.getImgSrc}
                                              submitPost={this.submitPost}
                                                test={this.test}
                                                  question={this.state.question}

                />}
              />



                <Route
                      exact path={`/dashboard/post${this.state.openedPost}`}
                      ponent={() =>
                        <SinglePost posts={this.state.posts}
                                      openedPost={this.state.openedPost}
                                       getAnswer={this.getAnswer}
                                        makeAnswer={this.makeAnswer}
                                          submitAnswer={this.submitAnswer}
                                            showAnswers={this.showAnswers}
                                              renderAnswers={this.renderAnswers}
                                                renderFavorite={this.renderFavorite}
                                                  userFavorited={this.userFavorited}
                                                    back={this.back}

                      />
                    }

                    />






      </div>
    </Router>
    );
  }

Dashboard.js

import React, { Component } from 'react';
import Navagationbar from  '../../ponents/Navigation/Navagationbar';
import Header from  '../../ponents/Header/Header';
import SignUpButton from  '../../ponents/SignUp/SignUpButton';
import AddPostForm from './AddPostForm';
import './styles.css';

import {
  Link
} from 'react-router-dom'

class Dashboard extends Component {
  render() {


    let renderedPosts = null;



    let createPostButton =  <div className="container" ><button className="button-primary" onClick={this.props.formOpen}> Create Post </button> </div>;

    if(this.props.openedPost) {
      renderedPosts = null;
      createPostButton = null;
    }
    else {
      renderedPosts = this.props.renderPosts();
    }

        let createPostForm = null;
        const openedForm = this.props.form;
        if(openedForm) {
        createPostForm =
              <AddPostForm
                formClose={this.props.formClose}
                    posts={this.props.posts}
                      getPostId={this.props.getPostId}
                        getQuestion={this.props.getQuestion}
                          makePost={this.props.makePost}
                            getBody={this.props.getBody}
                              getPostType={this.props.getPostType}
                                getImgSrc={this.props.getImgSrc}
                                    submitPost={this.props.submitPost}
                                      question={this.props.question}

                                    />

          createPostButton = null;
        }
        console.log("OPENED FORM IS " + openedForm)
    return (
    <div >
      <SignUpButton />
      <Header />
      <button onClick={this.props.test}/>
      {this.props.openedPost ? null : <Navagationbar />}



        {createPostForm}
        <div className="row">
          <div>
            {createPostButton}
          </div>
        </div>

        <div className="row">



        </div>
      <div className="row">
        <div className="twelve columns">
            {renderedPosts}
        </div>
      </div>

    </div>
    );
  }
}


export default Dashboard;

AddPostForm.js

import React, { Component } from 'react';
import './styles.css';

class AddPostForm extends Component {
    render() {
    return(
      <div className="container">



      <div className="row">
            <div className="six columns">
              <label>Post Title</label>
                <input onChange={this.props.getQuestion} value={this.props.question} className="u-full-width" type="search" placeholder="title" id="exampleEmailInput"/>
            </div>

              <div className="six columns">
                <label>Post Type</label>
                  <select value={this.props.type} onChange={this.props.getPostType} className="u-full-width">
                    <option value="Question">Question</option>
                    <option value="Discussion">Discussion</option>

                 </select>
              </div>
        </div>
            <div className="row">
              <div className="twelve columns">
                <label>Post</label>
                  <textarea onChange={this.props.getBody}  className="u-full-width" placeholder="get some clout" id="postMessage"></textarea>
                <label>
                  <span>Image Link</span> <br />
                    <input type="search"  onChange={this.props.getImgSrc}/>
                </label>
                  <input className="button-primary" type="button" value="submit" onClick={this.props.submitPost}/>
                  <button onClick={this.props.formClose}>Cancel </button>
               </div>
            </div>

    </div>

    );
  }
}

export default AddPostForm;

edit: After removing event.preventDefault() from getQuestion I can type but why does the input field unfocus after typing a single letter.

Is it because after every time I type the input field re-renders?

edit: Added majority of the code as requested.

This is sufficient in my opinion let me know if you want the rest of the functions.

Once I started passing props from parent to child to child I have been getting this problem where the getQuestion function only gets me the first letter typed, In addition in the input field nothing shows up.

Before when my code was just Parent to child it worked.

I want to know what exactly is going on because I have tried debugging by console logging and all I know is certain is that it only registers the first letter.

This question did not help because I have not misspelled onChange.

Can't type in React input text field

App.js

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



    this.getPostId = this.getPostId.bind(this);
    this.getQuestion = this.getQuestion.bind(this);
    this.makePost = this.makePost.bind(this);
    this.getBody = this.getBody.bind(this);
    this.getPostType = this.getPostType.bind(this);
    this.getImgSrc = this.getImgSrc.bind(this);
    this.submitPost = this.submitPost.bind(this);
    this.formOpen = this.formOpen.bind(this);
    this.formClose = this.formClose.bind(this);

    this.back = this.back.bind(this);
    this.showPost = this.showPost.bind(this);
    this.renderPosts = this.renderPosts.bind(this);

    //Answer/Response methods
    this.makeAnswer = this.makeAnswer.bind(this);
    this.getAnswer = this.getAnswer.bind(this);
    this.submitAnswer = this.submitAnswer.bind(this);

    this.state = {
      posts: [],

        answers: [],

      question: '',
      body: '',
      postType: 'Question',
      imgSrc: '',
      form: false,
      openedPost: null,
      answer: '',
      favorited: false,

      //sign up
      email:'',
      password: '',
      user: null

    }

}
getQuestion(event) {
  event.preventDefault();
  this.setState({ question:event.target.value });
}


render() {


    return (

      <Router>
        <div className="container">
          <Route
                  exact path={"/"}
                  ponent={() => <Home />}
          />

          <Route
                  exact path={"/home"}
                  ponent={() => <Home />}
          />

          <Route
                exact path={"/signup"}
                ponent={() => <SignUp />}
          />

          <Route
                exact path={`/dashboard`}
                ponent={() =>
                  <Dashboard back={this.back}
                    form={this.state.form}
                      openedPost={this.state.openedPost}
                        renderPosts={this.renderPosts}
                          formClose={this.formClose}
                            formOpen={this.formOpen}
                              posts={this.state.posts}
                                getPostId={this.getPostId}
                                  getQuestion={this.getQuestion}
                                    makePost={this.makePost}
                                      getBody={this.getBody}
                                        getPostType={this.getPostType}
                                          getImgSrc={this.getImgSrc}
                                              submitPost={this.submitPost}
                                                test={this.test}
                                                  question={this.state.question}

                />}
              />



                <Route
                      exact path={`/dashboard/post${this.state.openedPost}`}
                      ponent={() =>
                        <SinglePost posts={this.state.posts}
                                      openedPost={this.state.openedPost}
                                       getAnswer={this.getAnswer}
                                        makeAnswer={this.makeAnswer}
                                          submitAnswer={this.submitAnswer}
                                            showAnswers={this.showAnswers}
                                              renderAnswers={this.renderAnswers}
                                                renderFavorite={this.renderFavorite}
                                                  userFavorited={this.userFavorited}
                                                    back={this.back}

                      />
                    }

                    />






      </div>
    </Router>
    );
  }

Dashboard.js

import React, { Component } from 'react';
import Navagationbar from  '../../ponents/Navigation/Navagationbar';
import Header from  '../../ponents/Header/Header';
import SignUpButton from  '../../ponents/SignUp/SignUpButton';
import AddPostForm from './AddPostForm';
import './styles.css';

import {
  Link
} from 'react-router-dom'

class Dashboard extends Component {
  render() {


    let renderedPosts = null;



    let createPostButton =  <div className="container" ><button className="button-primary" onClick={this.props.formOpen}> Create Post </button> </div>;

    if(this.props.openedPost) {
      renderedPosts = null;
      createPostButton = null;
    }
    else {
      renderedPosts = this.props.renderPosts();
    }

        let createPostForm = null;
        const openedForm = this.props.form;
        if(openedForm) {
        createPostForm =
              <AddPostForm
                formClose={this.props.formClose}
                    posts={this.props.posts}
                      getPostId={this.props.getPostId}
                        getQuestion={this.props.getQuestion}
                          makePost={this.props.makePost}
                            getBody={this.props.getBody}
                              getPostType={this.props.getPostType}
                                getImgSrc={this.props.getImgSrc}
                                    submitPost={this.props.submitPost}
                                      question={this.props.question}

                                    />

          createPostButton = null;
        }
        console.log("OPENED FORM IS " + openedForm)
    return (
    <div >
      <SignUpButton />
      <Header />
      <button onClick={this.props.test}/>
      {this.props.openedPost ? null : <Navagationbar />}



        {createPostForm}
        <div className="row">
          <div>
            {createPostButton}
          </div>
        </div>

        <div className="row">



        </div>
      <div className="row">
        <div className="twelve columns">
            {renderedPosts}
        </div>
      </div>

    </div>
    );
  }
}


export default Dashboard;

AddPostForm.js

import React, { Component } from 'react';
import './styles.css';

class AddPostForm extends Component {
    render() {
    return(
      <div className="container">



      <div className="row">
            <div className="six columns">
              <label>Post Title</label>
                <input onChange={this.props.getQuestion} value={this.props.question} className="u-full-width" type="search" placeholder="title" id="exampleEmailInput"/>
            </div>

              <div className="six columns">
                <label>Post Type</label>
                  <select value={this.props.type} onChange={this.props.getPostType} className="u-full-width">
                    <option value="Question">Question</option>
                    <option value="Discussion">Discussion</option>

                 </select>
              </div>
        </div>
            <div className="row">
              <div className="twelve columns">
                <label>Post</label>
                  <textarea onChange={this.props.getBody}  className="u-full-width" placeholder="get some clout" id="postMessage"></textarea>
                <label>
                  <span>Image Link</span> <br />
                    <input type="search"  onChange={this.props.getImgSrc}/>
                </label>
                  <input className="button-primary" type="button" value="submit" onClick={this.props.submitPost}/>
                  <button onClick={this.props.formClose}>Cancel </button>
               </div>
            </div>

    </div>

    );
  }
}

export default AddPostForm;

edit: After removing event.preventDefault() from getQuestion I can type but why does the input field unfocus after typing a single letter.

Is it because after every time I type the input field re-renders?

edit: Added majority of the code as requested.

This is sufficient in my opinion let me know if you want the rest of the functions.

Share Improve this question edited Dec 18, 2017 at 1:20 codejockie 10.9k4 gold badges50 silver badges57 bronze badges asked Dec 17, 2017 at 17:13 OmarOmar 3,4213 gold badges24 silver badges41 bronze badges 9
  • You're doing event.preventDefault()??! – Andrew Li Commented Dec 17, 2017 at 17:15
  • okay, thats weird earlier that did not prevent me. That however does not fix it pletely. I think I need to focus the input because after typing a letter the user has to click on the input box again to type. Do you know why after typing one letter it unfocuses? @Li357 – Omar Commented Dec 17, 2017 at 17:18
  • Okay, theres a few questions I have seen on the react docs that i should maybe do <input onChange={this.props.getQuestion} value={this.props.question}/> question is just the string that I store the input in state in App.js. When I do that and take away event.prevent.default() I can type but the text unfocuses after every letter and the user has to click on it again. Now when I just remove event.preventDefault() with the code I have provided above does not allow me to type. @Li357 – Omar Commented Dec 17, 2017 at 17:24
  • Please could you show full code to each file, I might be able to help. – codejockie Commented Dec 17, 2017 at 17:36
  • @JohnKennedy added a majority of the code let me know if it is sufficient – Omar Commented Dec 17, 2017 at 17:48
 |  Show 4 more ments

3 Answers 3

Reset to default 3

Having gone through the code, I noticed all methods e from the root level ponent App. In which case when you type in the post title input field it immediately calls the parent getQuestion method which set state there by causing a re-render of the page which in turn causing the input field to lose focus.

Method 1:
To fix this I'd suggest you maintain state for the AddPostForm by allowing it manage its own state.

import React, { Component } from 'react';

class AddPostForm extends Component {
  state = {
    question: ""
  }

  setQuestion = (event) => {
    this.setState({
      question: event.target.value
    });
  }

  render() {
    return (
      <div className="container">
        <div className="row">
          <div className="six columns">
            <label>Post Title</label>
            <input
             onChange={this.setQuestion} // note change
             value={this.state.question} // note change
             className="u-full-width"
             type="search"
             placeholder="title"
             id="exampleEmailInput"
            />
          </div>
          ...
        </div>
      </div>
    );
  }
}

export default AddPostForm;

Method 2:
In App.js render method I made few changes that will allow you pass down props to the child ponents without the text fields loosing focus.

render() {
    return (

      <Router>
        <div className="container">
          <Route
            exact
            path="/"
            ponent={Home}
          />

          <Route
            exact
            path="/home"
            ponent={Home}
          />

          <Route
            exact
            path="/signup"
            ponent={SignUp}
          />

          <Route
            exact
            path="/dashboard"
            render={(props) =>
              <Dashboard
                {...props}
                back={this.back}
                body={this.state.body}
                form={this.state.form}
                openedPost={this.state.openedPost}
                renderPosts={this.renderPosts}
                formClose={this.formClose}
                formOpen={this.formOpen}
                posts={this.state.posts}
                getPostId={this.getPostId}
                getQuestion={this.getQuestion}
                makePost={this.makePost}
                getBody={this.getBody}
                getPostType={this.getPostType}
                getImgSrc={this.getImgSrc}
                submitPost={this.submitPost}
                test={this.test}
                question={this.state.question}
              />
            }
          />

          <Route
            exact
            path={`/dashboard/post${this.state.openedPost}`}
            render={(props) =>
              <SinglePost
                {...props}
                posts={this.state.posts}
                openedPost={this.state.openedPost}
                getAnswer={this.getAnswer}
                makeAnswer={this.makeAnswer}
                submitAnswer={this.submitAnswer}
                showAnswers={this.showAnswers}
                renderAnswers={this.renderAnswers}
                renderFavorite={this.renderFavorite}
                userFavorited={this.userFavorited}
                back={this.back}
              />
            }
          />
        </div>
      </Router>
    );
  }

In the Routes for dashboard I changed from using ponent prop of Route to using render prop instead. This fixes the issue.

To improve it you can clear the form after the state data is send to the parent ponent.

handleChange(e) {
 let { name, value } = e.target;

 // clone current state
 let clonedState = Object.assign({}, this.state);

 clonedState.data[name] = value;

 this.setState({
   data: clonedState.data,
 });
}

handleSubmit(e) {
  e.preventDefault();
  this.props.getQuestion(this.state.data)

  // clear state data
  this.setState({ data: {} });
}

It would be better to track changes in the ponent the user is actually typing in. Then onSubmit, call your getQuestion(this.state).

This would be in any form ponent a user is typing in.

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

  handleSubmit(e) {
    e.preventDefault();
    this.props.getQuestion(this.state)
  }

本文标签: javascripthow come eventtargetvalue is only capturing the first letter in string inputStack Overflow