0

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>
    );
  }
}

1 Answer 1

1

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>

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

4 Comments

It says TypeError: Attempted to assign to readonly property.
Where does it say, while doing what? You may be trying to assign to a non-existing property. It is hard to tell without seeing it. Could you link to the modified code?
Edit (Expo Snack) works great. Just the way I wanted it to be. Thanks a lot man! You're a saviour!
Also, remove this.state. from line no. 23 & 24 of your Expo Snack so that when the user reopens the app, the incremented value appears.

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.