I have two instances of a component which I want them to behave like toggle buttons. If I click on a specific component instance, the other component instances should get deselected.
The below is my code:
store.js:
import { configureStore } from '@reduxjs/toolkit'
import boxReducer from './slices/boxSlice'
export default configureStore({
reducer: {
box:boxReducer
}
})
boxSlice.js:
export const boxSlice = createSlice({
name: "box",
initialState: {
selected: false,
},
reducers: {
select: (state) => {
state.selected=true;
},
deselect: (state) => {
state.selected=false;
},
},
});
export const { select, deselect } = boxSlice.actions;
export default boxSlice.reducer;
Box.js:
export function Box(){
const selectedStatus = useSelector((state) => state.box.selected)
const dispatch = useDispatch()
const [status, setStatus] = useState("Unselected")
const onSelect = (e) => {
dispatch(select());
if (selectedStatus) {
setStatus("Selected")
dispatch(deselect());
} else {
setStatus("Unselected");
}
}
return (
<div tabIndex="0" onClick={onSelect} className="box">
{status}
</div>
)
}
This is buggy. What I am observing is:
- On first click the instance does not get updated. It gets updated only on second click
- It does not toggle properly. Both remain selected or unselected
How do I update the other instances of the component properly, whenever one of the instances is clicked
3
Answers
Instead of maintaining a separate
state
in your component, you can make use of the Redux state returned by theuseSelector
Try to click on the "Selected" and "Unselected" below to see it works:
After that, you can have another boolean flag (eg.
inverse
) to know that which of the 2 box’s component should be inversed.The redux state should be the source of truth. I suggest giving each box component a unique id and store the currently selected box id. If the same box id is already selected, deselect the box id, otherwise, set to the new id.
Example:
boxSlice.js
Box
App
Try this