0

I'm new to React Native and most of my progress so far has been due to my mad Copy-Paste skillz.

I have searched far and wide, so don't tell me to Google it.

GOAL: I want it toggle strike-through onPress for a single line item only.

Near as I can tell, when the User presses on the TouchableOpacity > ListItem:

  • it should toggle the strikeStatus,
  • which will add styles.strike
  • based on the this.state.strikeStatus ? styles.strike : false test in the titleStyle.

Ironically, I can get it to work for ALL the ListItems when it initially loads, but I can't get it to toggle. Please advise.

(Somewhere it said to put an onPress in both the TouchableOpacity AND the ListItem, but that made no sense to me. If that would work, please provide more detailed instructions.)

Expo Snack is here.

`export default class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          isLoading: true,
          items: [],
          strikeStatus: false,
        };
      }

      toggleStrike = (item) => {
        this.setState({
          strikeStatus: true
        });
      };

      render() {
        return (
          <Header
            placement="left"
            leftComponent={{ icon: 'menu', color: '#fff' }}
            centerComponent={{
              text: 'Shopping List',
              style: { fontFamily: 'Verdana', fontSize: 18, color: '#fff' },
            }}
            rightComponent={{ icon: 'settings', color: '#fff' }}
          />,
          <List containerStyle={styles.container}>
            <FlatList
              data={this.state.items}
              showsVerticalScrollIndicator={true}
              renderItem={({ item }) => (
                <TouchableOpacity
                  onPress={() => this.toggleStrike(this)}>
                  <ListItem
                    style={styles.item}
                    titleStyle={[
                      styles.item,
                      this.state.strikeStatus ? styles.strike : false
                    ]}
                    title={item.Name}
                    subtitle={item.Updated}
                    badge={{
                      value: item.Buy,
                      textStyle: styles.badge
                    }}
                  />
                </TouchableOpacity>
              )}
            />
          </List>
        );
      }
    }

    const styles = StyleSheet.create({
      strike: {
        textDecorationLine: 'line-through',
        textDecorationStyle: 'solid'
      }
    });`
AimFireReady
  • 81
  • 2
  • 14

1 Answers1

1

In the first place, you are applying the same styles to all the items because the state variable strikeStatus is setting on any item you press and then it is used for all of them.

To achieve what you want, you can add an attribute to the item object called selected initialized on false.

The titleStyle will be:

titleStyle={[
    styles.item,
    item.selected && styles.strike
]}

Then you call onPress like this:

onPress={() => this.toggleStrike(index)}

To use index parameter you need to add it to the renderItem function

And inside toggleStrike you change the selected value to true of the item at the passed index.

toggleStrike(index) {
    this.setState((prevState) => {
        prevState.items[index].selected = !prevState.items[index].selected;
        return { ...prevState }
    });
} 
SebaKZ
  • 80
  • 5