MUHAMMAD Siyab
MUHAMMAD Siyab

Reputation: 446

Unable to update state (Array of Objects) : React

Since i'm new to react, i've worked little with react states. It is all fine when updating a simple state but the problems occurs when updating a state containing an array of objects. I've found some related answers on stackoverflow and other sites but still unable to find a better solution for the problem.

Initial states:

this.state = {
        article: [{
            title: '',
            category: '',
            author: '',
            desc: '',
            date: ''
        },
        {
            authorName: '',
            profile: '',
            joinedOn: ''

        }]
    }

Updating states:

<input type="text" name="title" placeholder="Enter article title" className="form-control" onChange={e => this.setState({article: [...this.state.article, {title: e.target.value}]})} />

Accessing states:

console.log(this.state.article[0].title)

Console is showing empty string.

Upvotes: 0

Views: 2484

Answers (2)

Arman Charan
Arman Charan

Reputation: 5797

Without too much of an idea of what's going on inside your component overall:

Your existing onChange() pushes a new article each time it's triggered.

An improvement might be to temporarily store the title value in this.state.

See below for a practical example.

// Articles.
class Articles extends React.Component {

  // State.
  state = {articles: [], title: ''}

  // Render.
  render() {
    const {articles, title} = this.state
    return (
      <React.Fragment>
        <form onSubmit={this.addArticle}>
          <input type="text" value={title} onChange={e => this.setState({title: e.target.value})}/>
          <button type="submit">Add article</button>
        </form>
        <h3>Articles</h3>
        {articles.map((article, index) => <div key={index}>{article.title}</div>)}
      </React.Fragment>
    )
  }
  
  // Add Article.
  addArticle = event => {
    event.preventDefault()
    const {title} = this.state
    if (!title) return console.error('Invalid title.')
    return this.setState(state => ({
      articles: state.articles.concat([{title}]),
      title: ''
    }))
  }
  
}

// Mount.
ReactDOM.render(<Articles/>, document.querySelector('#root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

Upvotes: 5

Josh Lin
Josh Lin

Reputation: 2437

<input type="text" name="title" placeholder="Enter article title" className="form-control" onChange={e => this.setState({article: [{
...this.state.article[0],
{title: e.target.value}
},this.state.article[1] ]})} />

Upvotes: 0

Related Questions