2

I'm simply trying to append a json created dynamically into an array that lives inside the state. The only way that I've found till now is to use concat, because push doesn't work.

    constructor() {
        super()
        this.state = {
            list: []
        }
        this.add = this.add.bind(this)
    }

    add(e) {
        e.preventDefault()
        var task = document.getElementById('task').value
        var json = JSON.parse(JSON.stringify({key: task, item: task}))
        this.setState({list: this.state.list.concat(json)}) // WORKS
        // this.setState({list: this.state.list.push(json)}) // DOESN'T WORK

        console.log(this.state.list)
        document.getElementById('task').value = ''

    }

That works, but I don't understand why I have an empty array in console after the first item it's created. I've read how concat works, but obviously I missed something. Why I can't push an object inside my this.list array?

3 Answers 3

6

The concat otherwise create a new array and return it.

The push returns the new length of the array, which means a number, which means NOT what you want to set to state.list. That's why it didn't work.

why I have an empty array in console

From the docs: setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. That's why you are getting the empty array in the console.

And one more thing, don't mutate your state directly. If you call state.list.push(...), your changes will not be maintained by React and will be discarded if you call setState later. So it's a good thing to use concat.

Sign up to request clarification or add additional context in comments.

6 Comments

Right, but do you know why I have an empty array in console after I create the first element? I expected to see the element I've just created
From the docs: facebook.github.io/react/docs/component-api.html#setstate: setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. That's why you are getting the empty array in the console. In another words, setState run asynchronously.
I'm wondering if my code could be a good approach or exists a better/cleaner way to append data into an array
Tips: don't use document.getElementById, use state and props. You might want to read this article to clearly know how to work in React: facebook.github.io/react/docs/thinking-in-react.html
the answer is totally misleading the problem is not what array.push return the problem is about mutation so react can know the difference between the state previous and current state changes also this.setState accept a callback function that can be used to know if the state change process is finished.
|
1

this.state is immutable and has to be changed only via the setState() function.

From the docs:

NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable. setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

So, the best way to do this is to replace the array in this.state by a new array, and not try to push/modify it.

var newState = Object.assign({}, this.state); // Clone the state obj in newState
newState[arrayKey].push(newItem);             // modify newState
this.setState(newState);                      // setState()

Comments

0

Array.prototype.push() returns the new length property of the object upon which the method was called.

See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/push#Returns

1 Comment

Damn, TrungDQ beat me to it :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.