user14212874
user14212874

Reputation: 65

How to add a value to array state?

I am trying to add a new value to state array but it gives me error.

code

async shouldComponentUpdate(prevProps) {
    if (prevProps.navigation.state.params.updated) {
      const { updated } = prevProps.navigation.state.params;
      // updated = object
      const { typeTwo, typeThree } = this.state;
      const typeTwoUpdated = await typeTwo.filter((v) => v.id !== updated.id);
      const typeThreeUpdated = await typeThree.push(updated);
      this.setState({ typeTwo: typeTwoUpdated, typeThree: typeThreeUpdated });
    }
  }

Error

> [Unhandled promise rejection: TypeError: typeThree.push is not a function. (In 'typeThree.push(updated)', 'typeThree.push' is undefined)]

Edit

Changed the code.

async shouldComponentUpdate(prevProps) {
    if (prevProps.navigation.state.params.updated) {
      const { updated } = prevProps.navigation.state.params;
      // updated = object
      const { typeTwo, typeThree } = this.state;
      // typeThree = []
      const typeTwoUpdated = typeTwo.filter((v) => v.id !== updated.id);
      this.setState({ typeTwo: typeTwoUpdated, typeThree: [...typeThree, updated] });
    }
  }

new error

[Unhandled promise rejection: Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.]

Upvotes: 0

Views: 109

Answers (3)

Slava Knyazev
Slava Knyazev

Reputation: 6081

Refer to: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

First of all, Array.prototype.push is a synchronous operation, it does not need await.

Secondly, it returns the length of the array when called and mutates the underlying array.

Example

const animals = ['pigs', 'goats', 'sheep'];

const count = animals.push('cows');
console.log(count);
// expected output: 4
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows"]

You have two ways of doing it:

Mutating

      typeThree.push(updated);
      this.setState({ typeTwo: typeTwo.filter((v) => v.id !== updated.id), typeThree });

Immutable (The right way)

      this.setState({ typeTwo: typeTwo.filter((v) => v.id !== updated.id), typeThree: [...typeThree, updated] });

Upvotes: 0

Anhdevit
Anhdevit

Reputation: 2104

Try this

async shouldComponentUpdate(prevProps) {
    if (prevProps.navigation.state.params.updated) {
      const { updated } = prevProps.navigation.state.params;
      // updated = object
      const { typeTwo, typeThree } = this.state;
      // typeThree = []
      const typeTwoUpdated = typeTwo.filter((v) => v.id !== updated.id);
      this.setState({ typeTwo: typeTwoUpdated, typeThree: [...typeThree, updated });
    }
  }

Upvotes: 0

doc_id
doc_id

Reputation: 1433

Check initial state, particularly state.typeThree. The shouldComponentUpdate could be run before you call this.setState({typeThree: Array})

Edit: Please do not add items to an array that is referenced in React component state.
const typeThreeUpdated = typeThree && typeThree.length ? [...typeThree] : [];

typeThreeUpdated.push(updated);

this.setState({ typeTwo: typeTwoUpdated, typeThree: typeThreeUpdated });

Edit 2: So here is what happens

const typeThreeUpdated = await typeThree.push(updated);

this line will result in typeThreeUpdated to be an integer value, which is the new length of typeThree after pushing a new element. The push mutates the array but returns not the new array, instead it returns the new length. Then it's stored in state as typeThree in this line

this.setState({ typeTwo: typeTwoUpdated, typeThree: typeThreeUpdated });

and in the next time the function runs, this.state.typeThree is still that number, which has no push function.

Note that you don't need await here

Upvotes: 1

Related Questions