简体   繁体   中英

Using React, JSX: how to retrieve input value, post it as an element, and then clear it to repeat

This is an assignment for school. It involves using React and JSX to create an input field and a submit button. When the button's clicked, the input value should render as an element to the body. I was able to create it for the first click, but don't know how to repeat it.

If you look at the code below, you'll see that when user types, handleChange changes state of input and when the button's clicked, handleClick changes the boolean state of the button (called 'post'). If post is true, the input along with a timestamp is rendered as a heading.

The problem is that after the render, the input isn't cleared. If the user changes input and clicks button again, it updates the heading with a new timestamp and new input instead of adding another heading.

I've tried changing back state for input and post in handleClick, handleChange, componentDidMount, and componentDidUpdate. But that repeatedly calls setState and I get an error message 'maximum update depth exceeded.'

So, what I want it to do is post a new heading of the input value every time the user clicks the post button. I also want it to clear the input/placeholder text.

 import React, { Component } from 'react'; import './App.css'; import Firstposts from './firstposts.jsx'; class App extends Component { constructor(props) { super(props) this.state = { input: "", post: false } this.handleChange = this.handleChange.bind(this); this.handleClick = this.handleClick.bind(this); } handleChange(event) { this.setState({ input: event.target.value }); } handleClick() { this.setState({ post: true }) } render() { let timestamp = new Date(); return ( <div className="container"> <div className="panel"> <img height="100 px" src="https://marketing.twitter.com/content/dam/marketing-twitter/brand/logo.png" alt=""></img> <h1>Chirper</h1> </div> <div className="body"> <input placeholder="type your message here" onChange={this.handleChange} /> <button onClick={this.handleClick} >Post</button> <h2>Log</h2> {<Firstposts />} {this.state.post ? <div> <h3>{timestamp.toString()}</h3> <h4>{this.state.input}</h4> </div> : <div /> } </div> </div > ); } } export default App; 

Update your handleClick method to set posts to an array of posts, instead of a boolean:

handleClick() {
  this.setState({
    posts: [
      ...this.state.posts,
      this.state.input
    ]
  })
}

This will add the value of this.state.input to the end of this.state.posts , preserving all previous posts.

You can update this further to clear the value of the input field:

handleClick() {
  this.setState({
    posts: [
      ...this.state.posts,
      this.state.input
    ],
    input: '' // add this line to clear your input field when a new post is submitted
  })
}

Also, make sure to give your <input> element a value of this.state.input :

<input
  value={this.state.input}
  placeholder="type your message here"
  onChange={this.handleChange}
/>

Without this, you will not be able to programmatically update the value of the <input> field by using setState . You can read more on uncontrolled components in React .

Then, update your render method to map over this.state.posts and render each one:

{this.state.posts.map(post => (
  <h4>{post}</h4>
))}

You can read more on rendering lists in React .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM