Reputation: 13
I am building a food delivery application, and I would like to know how I can limit the number of checkboxes selected. An example is when entering the subsidiary, it displays a list of products. If I select a pizza, there is an extras section that limits the number of extras you can select, if you want to select more than two and your limit is two it should not allow you
all this with react hooks, I attach a fragment of my component
const ExtrasSelector = ({options = [{}], onPress = () => {}, limit = 0}) => {
const [showOptions, setShowOptions] = useState(true);
const [selectedAmount, setSelectedAmount] = useState(0);
const EXTRA = ' extra';
const EXTRAS = ' extras';
const updatedList = options.map(data => ({
id: data.id,
name: data.name,
price: data.price,
selected: false,
}));
const [itemsList, setItemsList] = useState(updatedList);
const toggleOptions = () => setShowOptions(!showOptions);
useEffect(() => {
}, [selectedAmount]);
// onPress for each check-box
const onPressHandler = index => {
setItemsList(state => {
state[index].selected = !state[index].selected;
onPress(state[index], getSelectedExtras(state));
// Increments or decreases the amount of selected extras
if (state[index].selected) {
setSelectedAmount(prevState => prevState + 1);
} else {
setSelectedAmount(prevState => prevState - 1);
}
return state;
});
};
const getSelectedExtras = extrasArr => {
const selectedExsArr = [];
extrasArr.map(item => {
if (item.selected) {
selectedExsArr.push(item);
}
});
return selectedExsArr;
};
return (
<View>
<View style={styles.container}>
<TouchableOpacity style={styles.row} onPress={toggleOptions}>
<Text style={styles.boldTitleSection}>
Extras {'\n'}
<Text style={titleSection}>
Selecciona hasta {limit}
{limit > 1 ? EXTRAS : EXTRA}
</Text>
</Text>
<View style={styles.contentAngle}>
<View style={styles.contentWrapperAngle}>
<Icon
style={styles.angle}
name={showOptions ? 'angle-up' : 'angle-down'}
/>
</View>
</View>
</TouchableOpacity>
{showOptions ? (
itemsList.map((item, index) => (
<View key={index}>
<CheckBox
label={item.name}
price={item.price}
selected={item.selected}
otherAction={item.otherAction}
onPress={() => {
onPressHandler(index, item);
}}
/>
<View style={styles.breakRule} />
</View>
))
) : (
<View style={styles.breakRule} />
)}
</View>
</View>
);
};
Upvotes: 0
Views: 3248
Reputation: 6691
This is a simple react implementation of "checkboxes with limit" behaviour with useReducer
. This way the business logic (here the limitation but can be any) is implemented outside of the component in a pure js function while the component itself is just a simple reusable checkbox group.
const { useReducer } = React; // --> for inline use
// import React, { useReducer } from 'react'; // --> for real project
const reducer = (state, action) => {
if (state.checkedIds.includes(action.id)) {
return {
...state,
checkedIds: state.checkedIds.filter(id => id !== action.id)
}
}
if (state.checkedIds.length >= 3) {
console.log('Max 3 extras allowed.')
return state;
}
return {
...state,
checkedIds: [
...state.checkedIds,
action.id
]
}
}
const CheckBoxGroup = ({ data }) => {
const initialState = { checkedIds: [] }
const [state, dispatch] = useReducer(reducer, initialState)
return (
<table border="1">
{data.map(({ id, label }) => (
<tr key={id}>
<td>
<input
onClick={() => dispatch({ id })}
checked={state.checkedIds.includes(id)}
type="checkbox"
/>
</td>
<td>
{label}
</td>
</tr>
))}
</table>
)
};
const data = [
{ id: "1", label: "Mashroom" },
{ id: "2", label: "Ham" },
{ id: "3", label: "Egg" },
{ id: "4", label: "Ananas" },
{ id: "5", label: "Parmesan" },
]
ReactDOM.render(<CheckBoxGroup data={data} />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 2