Beep Boop
Beep Boop

Reputation: 337

React Native CheckBox and FlatList: Cannot Toggle, and can only select each item once

I am using import CheckBox from '@react-native-community/checkbox';.

I am only able to 'select' each 'item' once and cannot toggle it (change or re-toggle).

Any help would be appreciated and if there's alternate plugins/packages available feel free to suggest it.

Code snippet below:

 import CheckBox from '@react-native-community/checkbox';

 export default class FrCreateScreen extends Component {

    constructor(props) {
        super(props);
        this.state = {
            timeSlots: [
                { id: '1', time: '10am - 11am' },
                { id: '2', time: '11am - 12pm' },
                { id: '3', time: '12pm - 1pm' },
                { id: '4', time: '1pm - 2pm' },
                { id: '5', time: '2pm - 3pm' },
                { id: '6', time: '3pm - 4pm' },
                { id: '7', time: '4pm - 5pm' },
                { id: '8', time: '5pm - 6pm' },
            ],

            //checkBox
            checked: false,
        }
    }

    checkBox(value) {
        this.setState({
            checked: !value,
        })
    }

    getAppointmentTimePage() {
        const { checked, timeSlots } = this.state;

        return (
            <View>
                <Text style={[styles.title, { marginTop: 20 }]}>Select Appointment Time:</Text>
                {<FlatList
                    data={timeSlots}
                    keyExtractor={(times) => times.id}
                    renderItem={({ item }) => {
                        return (
                            <View style={styles.containerTime}>
                                <Text style={styles.textTime}>{item.time}</Text>
                                <CheckBox
                                    value={checked}
                                    onChange={() => this.checkBox(item.id)}
                                />
                            </View>
                        );
                    }}
                />}
                <TouchableOpacity style={styles.addContainer}>
                    <Text style={styles.addText}>Add Appointment</Text>
                </TouchableOpacity>
            </View>
        );
    }

    render() {
        return (
            <ScrollView>
                {this.getAppointmentTimePage()}
            </ScrollView>
        )
    };
};

Image Screenshot below:

Upvotes: 0

Views: 2338

Answers (2)

Tuan Luong
Tuan Luong

Reputation: 4162

You don't need to wrap FlatList inside a ScrollView. Try below code

import CheckBox from '@react-native-community/checkbox';

export default class FrCreateScreen extends Component {

  constructor(props) {
    super(props);
    this.state = {
        timeSlots: [
            { id: '1', time: '10am - 11am' },
            { id: '2', time: '11am - 12pm' },
            { id: '3', time: '12pm - 1pm' },
            { id: '4', time: '1pm - 2pm' },
            { id: '5', time: '2pm - 3pm' },
            { id: '6', time: '3pm - 4pm' },
            { id: '7', time: '4pm - 5pm' },
            { id: '8', time: '5pm - 6pm' },
        ],

        selectedValue: {},
    }
  }

  toggleItem = (itemId) => {
    const { selectedValue } = this.state;
    const isSelected = selectedValue[itemId];
    selectedValue[itemId] = !isSelected;

    this.setState({
      selectedValue: {...selectedValue},
    })
  }

  render() {
    const { timeSlots, selectedValue } = this.state;
    return (
      <View>
        <Text style={[styles.title, { marginTop: 20 }]}>Select Appointment Time:</Text>
        <FlatList
          data={timeSlots}
          keyExtractor={(times) => times.id}
          renderItem={({ item }) => {
            const isSelected = selectedValue[item.id];
              return (
                <View style={styles.containerTime}>
                  <Text style={styles.textTime}>{item.time}</Text>
                  <CheckBox
                    value={isSelected}
                    onChange={() => this.checkBox(item.id)}
                  />
                </View>
              );
          }}
          extraData={[selectedValue]}
        />
        <TouchableOpacity style={styles.addContainer}>
            <Text style={styles.addText}>Add Appointment</Text>
        </TouchableOpacity>
      </View>
    );
  };
};

Upvotes: 1

Sylvain
Sylvain

Reputation: 529

You have several problems in your code. First, your checked state should be an array. Then, you pass checkbox id in your function, so !value will always be false.

You could try this (I haven’t tried, you probably need to improve it):

import CheckBox from '@react-native-community/checkbox';

 export default class FrCreateScreen extends Component {

    constructor(props) {
        super(props);
        this.state = {
            timeSlots: [
                { id: '1', time: '10am - 11am' },
                { id: '2', time: '11am - 12pm' },
                { id: '3', time: '12pm - 1pm' },
                { id: '4', time: '1pm - 2pm' },
                { id: '5', time: '2pm - 3pm' },
                { id: '6', time: '3pm - 4pm' },
                { id: '7', time: '4pm - 5pm' },
                { id: '8', time: '5pm - 6pm' },
            ],

            //checkBox
            checked: [false, false, false, false, false, false, false, false],
        }
    }

    checkBox(index) {
      let checkedCopy = this.state.checked
      checkedCopy[index] = !checkedCopy[index]
        this.setState({
            checked: checkedCopy,
        })
    }

    getAppointmentTimePage() {
        const { checked, timeSlots } = this.state;

        return (
            <View>
                <Text style={[styles.title, { marginTop: 20 }]}>Select Appointment Time:</Text>
                {<FlatList
                    data={timeSlots}
                    keyExtractor={(times) => times.id}
                    renderItem={({ item,  index }) => {
                        return (
                            <View style={styles.containerTime}>
                                <Text style={styles.textTime}>{item.time}</Text>
                                <CheckBox
                                    value={checked[index]}
                                    onChange={() => this.checkBox(index)}
                                />
                            </View>
                        );
                    }}
                />}
                <TouchableOpacity style={styles.addContainer}>
                    <Text style={styles.addText}>Add Appointment</Text>
                </TouchableOpacity>
            </View>
        );
    }

    render() {
        return (
            <ScrollView>
                {this.getAppointmentTimePage()}
            </ScrollView>
        )
    };
};

Upvotes: 0

Related Questions