How to Implement Multiple Checkbox Using React Hook

How to handle multiple checkboxes using React Hook

Well, the problem is solved. It's all about input attributes. I was passing htmlFor property into ListItem for item.name, but not for id. So I needed to create an id property in my checkboxes array and pass htmlFor property like this htmlFor={item.id}

Don't forget to pass id property to ListItem as well like id={item.id}

ReactJS: Manage multiple checkbox inputs with useState

The basic problem is checked={allChecked ? true : isChecked[test.name]} stops the unchecking action from happening - once allChecked is true it does not matter what value isChecked[test.name] has, the expression is always going to be true.

You should rely only on isChecked for the value, and treat changing allChecked as a side-effect.

  useEffect(() => {
setIsChecked(current => {
const nextIsChecked = {}
Object.keys(current).forEach(key => {
nextIsChecked[key] = allChecked;
})
return nextIsChecked;
});
}, [allChecked]);

...

{formData.map((test, index) => (
<div key={index}>
<label>{test.name}</label>
<input
type="checkbox"
name={test.name}
checked={isChecked[test.name]}
onChange={handleSingleCheck}
/>
</div>
))}

There's also this warning cropping up

Warning: A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.

So that's basically saying don't initialize isChecked to {}, because the input's checked property is initially undefined. Use this instead,

{
test1: false,
test2: false,
test3: false,
test4: false,
test5: false,
}

or this way

const data = { ... }

const initialIsChecked = data.reduce((acc,d) => {
acc[d.name] = false;
return acc;
}, {})

export default function App() {
const [allChecked, setAllChecked] = useState(false);
const [isChecked, setIsChecked] = useState(initialIsChecked);
...

How to work with multiple checkboxes in react and collect the checked checkboxes

Your CheckBox-component does not contain a key property. This is helpful for React to identify which items have changed, are added, or are removed.

Source: https://reactjs.org/docs/lists-and-keys.html

I also do not understand why you have two states, checkboxState and checkedCheckboxes. Is there another reason for this? I think this would be easier with a single state which holds the indexes (or values) of the checked checkboxes.

[update after comments]

The code below is the desired solution by OP to have the selected object values in a React state.

const { useState } = React;

const Checkboxes = () => {
// With this useState I wan't to collect the checked checkboxes
const [checkedCheckboxes, setCheckedCheckboxes] = useState([]);

// This is my handler method that gets triggered when a checkbox get's checked/unchecked
// ..and toggles the state of the checkbox
const handleCheckboxChange = (data) => {
const isChecked = checkedCheckboxes.some(checkedCheckbox => checkedCheckbox.value === data.value)
if (isChecked) {
setCheckedCheckboxes(
checkedCheckboxes.filter(
(checkedCheckbox) => checkedCheckbox.value !== data.value
)
);
} else {
setCheckedCheckboxes(checkedCheckboxes.concat(data));
}
};

const receivedData = [{ value: "A" }, { value: "B" }, { value: "C" }];

return (
<>
<div className="checkboxes">
<h1>Checkboxes:</h1>
{receivedData?.map((data, index) => (
<input
key={`cb-${index}`}
value={data.value}
type="checkbox"
checked={checkedCheckboxes.some(checkedCheckbox => checkedCheckbox.value === data.value)}
onChange={() => handleCheckboxChange(data)}
/>
))}
</div>
<div>
<h1>State:</h1>
<pre>{JSON.stringify(checkedCheckboxes, null, 2)}</pre>
</div>
</>
);
};

ReactDOM.render(<Checkboxes />, document.getElementById("app"));

react hook how to handle mutiple checkbox

On every re-render you are basically setting isChecked property to false. Try updating your component like this:

const CurrentLists = ({ shoppingList }) => {
const [checkedItems, setCheckeditems] = useState(shoppingList)

const handleOnChange = useCallback(
(e) => {
const index = e.target.name
let items = [...checkedItems];
items[index].isChecked = e.target.checked;
setCheckeditems(items);
}, [checkedItems]
);
return (
<div>
{checkedItems.map((item, index) => {
console.log('item check', item.isChecked)
return (
<CheckBox
key={index}
name={index}
checked={item.isChecked}
text={item.name}
onChange={handleOnChange}
/>
)
})}
</div>
)
}

You may also notice usage of useCallback. It ensures that your callback is memoized and not created on every re-render - more about it.

Handling dynamic checkbox in react-native using hooks

Try this way

const CheckTest = () => {
const [data, setData] = useState([
{
name: 'first'
},
{
name: 'second'
},
{
name: 'third'
},
{
name: 'fourth'
}]);



const onValueChange = (item, index) => {
const newData = [...data];
newData[index].isCheck = !item.isCheck;
setData(newData);
}

return (
<View style={{ paddingTop: 20 }}>
{data.map((item, index) => {
return <CheckBox
title={item.name}
checked={item.isCheck || false}
onPress={(val) => onValueChange(item, index)}
key={item.name}
/>
})}


</View>
)
}

React Select All for multiple checkboxes

You can just have an array at the top to define checkboxes and create the initial state. Then loop into the array to display the checkboxes. Try below code

const dataArray = ['nr1', 'nr2'];
const initialState = dataArray.reduce((o, key) => ({ ...o, [key]: false}), {})

export default function App() {
const [checkedAll, setCheckedAll] = useState(false);
const [checked, setChecked] = useState(initialState);

...
...
return (
<div className="App">
<div>
<label>All</label>
<input
type="checkbox"
onChange={(event) => selectAll(event.target.checked)}
checked={checkedAll}
/>
</div>
{dataArray.map(data => (
<div>
<label>{data}</label>
<input
type="checkbox"
name={data}
onChange={() => toggleCheck(data)}
checked={checked[data]}
/>
</div>
))}
</div>
);


Related Topics



Leave a reply



Submit