I have a parent component that maps out a list of child component. Each child component has their own props like name, id, etc. I want to persist the checkbox is checked value on page refresh so I am using redux for storage. When I check/uncheck an individual checkbox, all the others checkboxes also gets checked/unchecked.
component file
const Daily = ({ daily, character_id }) => {
const { dailyName, id } = daily;
const checkbox = useSelector(checkboxSelector)
const dispatch = useDispatch()
const deleteDaily = async (id) => {
const dailyDoc = doc(db, `charactersDailies/${character_id}/dailies`, id)
await deleteDoc(dailyDoc)
window.location.reload(false)
}
return (
<div className="dailyContainer">
<input
className="dailyCheckbox"
id={daily.id}
type="checkbox"
checked={checkbox}
onChange={() => dispatch(setCheckboxAction(daily.id))}
/>
<label className="dailyName" htmlFor={daily.id}>
<h4 className="dailyName">{dailyName.toUpperCase()}</h4>
</label>
<h4 className="deleteDailyBTN" onClick={() => deleteDaily(id)}>
✕
</h4>
</div>
)
};
export default Daily;
redux action file
export const setCheckboxAction = (id) => {
return {
type: 'SET-CHECKBOX',
payload: id
}
};
redux reducer file
const checkboxReducer = (state = null, action) => {
switch(action.type) {
case 'SET-CHECKBOX':
return !state
default:
return state
}
};
export default checkboxReducer;
How do I only access each individual checkbox state from redux instead of all of the checkboxes?
All the checkboxes are using the same single checked state since it's a boolean.
export const setCheckboxAction = (id) => {
return {
type: 'SET-CHECKBOX',
payload: id
}
};
const checkboxReducer = (state = null, action) => {
switch(action.type) {
case 'SET-CHECKBOX':
return !state // <-- single boolean state
default:
return state
}
};
const Daily = ({ daily, character_id }) => {
...
const checkbox = useSelector(checkboxSelector); // <-- single state
...
return (
<div className="dailyContainer">
<input
...
checked={checkbox} // <-- single state
...
/>
...
</div>
)
};
Use the passed id
payload of the setCheckboxAction
action to conditionally toggle a specific checkbox by id. Convert the checkbox
state to an object/map that uses the passed id
as a computed property and toggles the truthy/falsey value. The UI will check the value using daily.id
.
Example:
const checkboxReducer = (state = {}, action) => {
switch(action.type) {
case 'SET-CHECKBOX':
return {
...state,
[action.payload]: !state[action.payload], // payload -> id
};
default:
return state;
}
};
const Daily = ({ daily, character_id }) => {
const { dailyName, id } = daily;
const checkboxes = useSelector(checkboxSelector);
const dispatch = useDispatch();
const deleteDaily = async (id) => {
const dailyDoc = doc(db, `charactersDailies/${character_id}/dailies`, id)
await deleteDoc(dailyDoc)
window.location.reload(false)
}
return (
<div className="dailyContainer">
<input
className="dailyCheckbox"
id={daily.id}
type="checkbox"
checked={checkboxes[daily.id]}
onChange={() => dispatch(setCheckboxAction(daily.id))}
/>
<label className="dailyName" htmlFor={daily.id}>
<h4 className="dailyName">{dailyName.toUpperCase()}</h4>
</label>
<h4 className="deleteDailyBTN" onClick={() => deleteDaily(id)}>
✕
</h4>
</div>
);
};