Search code examples
javascriptarraysreactjsreact-nativesetstate

How to access, update and save array index in React Native?


I am using two arrays present_count and total_count.

present_count[0] will store the count for the first subject (how many times blue button is clicked for the first subject), present_count[1] will store for the next subject and so on.

total_count[0] will store the count for the first subject (how many times blue/ red button is clicked for the first subject), total_count[1] will store for the next subject and so on.

present_count[i] will appear on LHS of slash sign and total_count[i] will appear on the RHS of slash sign.

output

state = {
    subjects: [],
    text: "",
    present_count: [],
    total_count: [],
}

present = i => {
    this.setState({
      present_count: this.state.present_count[i] + 1,
      total_count: this.state.total_count[i] + 1
    });
    AsyncStorage.setItem('PRESENT_COUNT', this.state.present_count[i].toString());
    AsyncStorage.setItem('TOTAL_COUNT', this.state.total_count[i].toString());
};

total = i => {
    this.setState({
      total_count: this.state.total_count[i] + 1,
    });
    AsyncStorage.setItem('TOTAL_COUNT', this.state.total_count[i].toString());
};

componentDidMount() {
    AsyncStorage.getItem('PRESENT_COUNT').then((value) => {
      this.setState({ present_count: parseInt(value) });
    });
    AsyncStorage.getItem('TOTAL_COUNT').then((value) => {
      this.setState({ total_count: parseInt(value) });
    });
}

render() {
    let tick = "\u2713", cross = "\u2573";
    return (
      <View style={[styles.container, { paddingBottom: this.state.viewPadding }]}>
        <FlatList style={styles.list}
          data={this.state.subjects}
          renderItem={({item, index }) => {
            return (
              <View>
                <View style={styles.listItemCont}>
                  <Text style={styles.listItem}> { item.text } </Text>
                  <View style={styles.buttonContainer}>
                    <Text style={styles.listItem}>
                          {this.state.present_count[index]} / {this.state.total_count[index]}
                    </Text>
                    <View style={styles.button}>
                      <Button title={tick} onPress={() => this.present(index)} color="blue" />
                    </View>
                    <View style={styles.button}>
                      <Button title={cross} onPress={() => this.total(index)} color="red" />
                    </View>
                  </View>
                </View>
                <View style={styles.hr} />
              </View>
            )
          }}
          keyExtractor={ (item, index) => index.toString()}
        />
      </View>
    );
  }
}

Solution

  • Question is not really about FlatList, there are other problems. One of them is modifying array state in react. To modify the value at index, do

    let present_count = [...this.state.present_count];  // shallow copy to avoid mutation
    present_count[i]++;  // increment
    this.setState({ present_count });  // update state
    
    • If you want to store the array as single integers in AsyncStorage, use unique keys for each of them. Note +i
    AsyncStorage.setItem('PRESENT_COUNT'+i, this.state.present_count[i]);
    
    • Otherwise, if what you want is saving the whole array to AsyncStorage, then do so.
    AsyncStorage.setItem('PRESENT_COUNT', JSON.stringify(this.state.present_count));
    AsyncStorage.getItem('PRESENT_COUNT').then((value) => {
        this.setState({ present_count: JSON.parse(value) });
    });
    

    You have to decide whether present_count is an array or an integer.

    state = {
        present_count: [],  // it is an array
    ...
    componentDidMount() {
        AsyncStorage.getItem('PRESENT_COUNT').then((value) => {
          this.setState({ present_count: parseInt(value) });  // you are parsing it as an integer
        });
    

    If you want to store many integers, then check out multiget to load multiple keys to present_count array in componentDidmount. Else just get & parse whole array with JSON.parse(value).


    Edit: Here is a working Expo Snack to illustrate it.

    <div data-snack-id="iQlK1UHAj" data-snack-platform="web" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.08);border-radius:4px;height:505px;width:100%"></div>
    <script async src="https://snack.expo.io/embed.js"></script>