3

I have an array in my state in my React Native project, like this:

constructor(props) {
  super(props)
  this.state = {
    a: [1, 2, 3]
  }
}

I click a button to update the array, like this:

<TouchableOpacity
  onPress={() => {this.setState({a: [5, 6]})}
/>

I want to verify the state change in my componentDidUpdate() method, like this:

componentDidUpdate(prevProps, prevState) {
  console.log("prevState: ", prevState)
  console.log("state: ", this.state)
}

but this always gives

prevState:  (5) [-1, -1, -1, -1, -1]
state:  (5) [-1, -1, -1, -1, -1]

I confirmed using devTools that the array is indeed updating to [5, 6], but the componentDidUpdate() method is still just returning the old value. Any idea why?

Thanks!

reisdev
  • 3,215
  • 2
  • 17
  • 38
gkeenley
  • 6,088
  • 8
  • 54
  • 129
  • try to add an `ìf (this.state !== this.prevState) { /* ... */ }` , as the [docs](https://reactjs.org/docs/react-component.html#componentdidupdate) recommend. – reisdev Mar 27 '19 at 02:01

3 Answers3

3

componentDidUpdate() should always be wrapped in a condition in order you need to add setState() method.

According to the docs:https://reactjs.org/docs/react-component.html#componentdidupdate

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance

Also check this answer for your referece: Correct modification of state arrays in ReactJS

Ankush Rishi
  • 2,861
  • 8
  • 27
  • 59
2

I did implement your code, mine is working.

here is my code:

import React, { Component } from "react";
import { View, Text, Button, SafeAreaView } from "react-native";

import { baseStyles as styles  } from "../styles";

export default class Fetch extends Component{
  constructor(props) {
    super(props)
    this.state = {
      a:[1, 2, 3]
    }
  }

  componentDidUpdate(prevProps, prevState) {
    console.log("prevState: ", prevState)
    console.log("state: ", this.state)
    alert(this.state.a)
  }

  render(){
    return(
    <SafeAreaView>

        <View style={styles.container}>
        <Text>
            Main Dish
        </Text>
        <Button
        title='press'
  onPress={() => {this.setState({a: [5, 6]})}}
/>
        </View>


    </SafeAreaView>

    )
  }
}
Mervzs
  • 1,114
  • 7
  • 21
  • 1
    Thanks Mervys! It ended up actually being an error elsewhere. Thanks for confirming. I had to give the approved answer to the other guy, but I gave you the upvote and got a friend to as well. – gkeenley Mar 27 '19 at 16:56
  • Thanks friend!! :D – Mervzs Mar 27 '19 at 22:12
1
  1. Make sure you're comparing two arrays with :
componentDidUpdate(prevProps){
  if(JSON.stringify(prevProps.todos) !== JSON.stringify(this.props.todos){...}
}
  1. Make sure you are changing the passed prop (state in parent) after deep cloning it:
let newtodos = JSON.parse(JSON.stringify(this.state.todos));
newtodos[0].text = 'changed text';
this.setState({ todos : newtodos });
yaya
  • 7,675
  • 1
  • 39
  • 38