Reputation: 25
I wanted to store array objects in react state. I don't know what I'm missing but my code is not working. Here is my code below :
export default class Groups extends React.Component {
constructor(props) {
super(props);
this.state = {
tabledata: []
}
}
componentDidMount() {
this.setState({
tabledata: [...this.state.tabledata, {"name": "name1"}]
})
console.log("HI")
console.log(this.state.tabledata)
}
}
The console log return empty state not storing anyting in state array.. Please suggest what's wrong here. Thank you in advance..
Upvotes: 0
Views: 159
Reputation: 60
You can push the object(s) into the array:
export default class Groups extends React.Component {
constructor(props) {
super(props);
this.state = {
tabledata: []
}
}
componentDidMount() {
this.setState({
// tabledata: [...this.state.tabledata, {"name": "name1"}]
tabledata: this.state.tabledata.push({"name": "name1"})
})
console.log("HI")
console.log(this.state.tabledata)
}
Upvotes: 1
Reputation: 1075457
There are two separate problems there, but both spring from the same cause: State updates are asynchronous.
So the two problems are:
You're setting state based on existing state by passing an object into setState
. That could set stale state. When updating state based on existing state, you must use the callback version of setState
.
You're logging state immediately after calling setState
. That won't see the updated state, because the update is asynchronous. Instead, log it in the completion callback (if you need to do something with it; normally, you don't need this, just allow React to re-render, which it will do by default).
Here are those corrections applied to your code:
export default class Groups extends React.Component {
constructor(props) {
super(props);
this.state = {
tabledata: []
}
}
componentDidMount() {
this.setState(
// Update callback receives the current state. Here I'm picking
// `tabledata` from it via destructuring
({tabledata}) => ({
tabledata: [...tabledata, {"name": "name1"}]
}),
// Completion callback
() => {
console.log("HI")
console.log(this.state.tabledata)
}
)
}
}
Live Example:
class Groups extends React.Component {
constructor(props) {
super(props);
this.state = {
tabledata: []
}
}
componentDidMount() {
this.setState(
({tabledata}) => ({
tabledata: [...tabledata, {"name": "name1"}]
}),
() => {
console.log("HI")
console.log(this.state.tabledata)
}
)
}
render() {
return this.state.tabledata.map(({name}) => <div>{name}</div>);
}
}
ReactDOM.render(<Groups />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
Again, though, normally you don't need or want to use the completion callback, so:
export default class Groups extends React.Component {
constructor(props) {
super(props);
this.state = {
tabledata: []
}
}
componentDidMount() {
this.setState(({tabledata}) => ({
tabledata: [...tabledata, {"name": "name1"}]
}));
}
}
Upvotes: 1