Checkbox does not deselect in React Native

Asked

Viewed 82 times

1

I’m using the hook useState, however it does not change the state when it is pressed again, it is always marked.

const [isSelected, setSelection] = useState({});

const handleChange = (event) => {
  setSelection({
    ...isSelected,
    [event.target.name]: event.target.checked
  });
};

const checkboxes = [
  {
    name: 'check-box-1',
    key: 'checkBox1',
    label: 'Check Box 1'
  },
  {
    name: 'check-box-2',
    key: 'checkBox2',
    label: 'Check Box 2'
  }
];

<Container>
<StatusBar />

<View style={styles.container}>

{checkboxes.map(item => (
    <View style={styles.checkboxContainer} >
        <CheckBox
          name={item.name}
          checked={isSelected[item.name]}
          onChange={handleChange}
        />
        <Text style={styles.label} > {item.name}</Text>
    </View>
))}

</View>
  • That one CheckBox, is React Native or is a third party component?

  • @React-Native-community/checkbox

  • OK. I understand where you’re going with this, but I don’t understand why you did it this way. Accept another way to solve it in response?

  • yes, any help is very welcome, the only restriction is that I have to use functions instead of class

1 answer

2


First, the attributes check and name do not exist in the component CheckBox, then we will not use them. We will only work with the following attributes:

  • value, which will store a boolean value (true/false);

  • onChange, who will be responsible for calling a function to handle the changes in the checkbox.

The logic, which in my view would be simpler, is you work with the array checkboxes as an initial state of useState, and every object contained therein, we may add a property that we shall call checked. In this checked will store a boolean value where true is for when the checkbox is selected, and false for when it’s not.

It would be like this:

const [isSelected, setSelection] = useState([
  {
    name: 'check-box-1',
    key: 'checkBox1',
    label: 'Check Box 1',
    checked: false
  },
  {
    name: 'check-box-2',
    key: 'checkBox2',
    label: 'Check Box 2',
    checked: false
  }
]);

The check-box-n will initially be unchecked (checked: false). Now we will make a similar loop to yours, only now we will do the map in isSelected and no longer in checkboxes:

{isSelected.map((item, index) => (
  <View key={index}>
    <CheckBox
      value={item.checked}
      onChange={() => handleChange(item.name)}
    />
    <Text>{item.name}</Text>
  </View>
))}

I left the components above without the styles, because I built the code just to elaborate the answer. Make your adjustments :)

See that I used the index only to pass to key.

Now the above logic is quite simple. According to the state (isSelected), let’s render a CheckBox of each of the items that will mount this checkbox.

Now let’s talk about the function handleChange in onChange={() => handleChange(item.name)}. Note that I passed to this function, the name of the label that we will change the state when we select the checkbox.

The function handleChange:

const handleChange = (name: string) => {
  const newState = isSelected.map(el => {
    const label = el;

    if (el.name === name) {
      label.checked = !el.checked;
    }

    return label;
  });

  setSelection(newState);
};

Let’s go over the details:

  • newState will receive a new array based on the initial state of isSelected. Using the map, let’s return a modified array and what will this change look like? See below...

  • Within the function handleChange, label will receive the initial state of each element within the isSelected. Let’s check which label was changed thanks to the name we passed to the function handleChange. Remember?

//                             ↓↓↓↓ passamos aqui o nome do label que foi clicado                           
onChange={() => handleChange(item.name)}

Now inside the if, we verify that the label name that has been changed is the current map. If so, let’s go reverse the state of checked using the !:

if (el.name === name) {
  label.checked = !el.checked; // o que era "true" vira "false", e vice-versa
}

Why reverse? For when we click again on checkbox, he ceases to be true and becomes false, soon, the checkbox will be unmarked.

After all, we will change the old state to the new state using the setSelection(newState).

const handleChange = (name) => {
  const newState = isSelected.map(el => {
    const label = el;

    if (el.name === name) { // verificamos se o nome do label foi passado na função
      label.checked = !el.checked; // se sim, vamos alterar o estado do "checked"
    }

    return label;
  });

  setSelection(newState); // atualiza o estado
};

Final code:

const [isSelected, setSelection] = useState([
  {
    name: 'check-box-1',
    key: 'checkBox1',
    label: 'Check Box 1',
    checked: false
  },
  {
    name: 'check-box-2',
    key: 'checkBox2',
    label: 'Check Box 2',
    checked: false
  }
]);

const handleChange = name => {
  const newState = isSelected.map(el => {
    const label = el;

    if (el.name === name) {
      // verificamos se o nome do label foi passado na função
      label.checked = !el.checked; // se sim, vamos alterar o estado do "checked"
    }

    return label;
  });

  setSelection(newState); // atualiza o estado
};
<View>
  {isSelected.map((item, index) => (
    <View key={index}>
      <CheckBox
        value={item.checked}
        onChange={() => handleChange(item.name)}
      />
      <Text>{item.name}</Text>
    </View>
  ))}
</View>
  • 1

    friend(a) THANK YOU VERY MUCH, you saved my kkk, I was complicating a lot... I understood everything, I really appreciate the help you gave me, I hope that one day I can repay, thank you very much

  • but what’s the difference between putting the key={index} inside the view and inside the checkbox component?

  • the keys (key) used in the arrays must be unique among their sister elements, in this case the View, so the key should be on View. You are rendering several Views within the map.

  • ok thank you so much for the explanation ! thanks for the help!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.