Originally published at https://www.wisdomgeek.com on August 25, 2020.
React hooks have been around for quite some time. They have been widely ado...
For further actions, you may consider blocking this person and/or reporting abuse
This post has been really helpful to me. I am building a class selection app and I was able to modify the form to pull from a list array. I am struggling to figure out how to toggle a boolean value in the reducer and localStorage, though. I need to be able to detect whether the item was selected throughout various components in the app so that I can prevent it from being selected twice.
Do you have any tips on how to prevent duplicates?
items.js
const itemsReducer = (state, action) => {
switch (action.type) {
case 'POPULATE_ITEMS':
return action.items;
case 'ADD_ITEM':
return state.concat({ name: action.name, info: action.info });
case 'REMOVE_ITEM':
return state.filter((item) => item !== action.itemToBeDeleted);
default:
return state;
}
};
export { itemsReducer as default };
AddItemForm.js
(Each item in my "individualClassList" array has a boolean
isSelected: false
)Everything else is essentially the same as your example. I tried adding the
isSelected
boolean to the itemReducer "ADD_ITEM" case, but I couldn't figure out how to add it to the "REMOVE_ITEM" case. I've been banging my head on this on for many days, so if you have any clues I would really appreciate the help!I think you are mixing two concepts: useState and useReducer. If you are using the reducer to update the state, you do not need to use useState again. I am not sure why you are doing that in the handleAdd and handleRemove methods. I would recommend reading more about useReducer to grasp it's concepts first. This post about useReducer should help you in doing that.
And for the remove not working, you are updating the value in the array with isSelected to false, not removing it. If you wanted to remove the entry on remove, you should use
Thank you so much for you response. It is really confusing because I am updating the state of two different arrays. One is my original list with items to select, which are added to a new list with the useReducer. In the original list I was adding useState to be able to detect whether an item in my original list has been selected so I can toggle the handleAdd/handleRemove function, and prevent duplicates from being added to my new list, but they are out of sync with each other.
Is there a way to prevent duplicates in the useReducer function? I am trying to concat and filter, but nothing is working and I have been reading about reducers and context until my eyes bug out. I feel like the answer could be as simple as concatenating the selected items and then filtering out the duplicates, but I only get errors or empty arrays when I do anything to this line.
case 'ADD_ITEM': return state.concat({ name: action.name, info: action.info });
you can change it to:
case 'ADD_ITEM':
if(state.find(obj => obj.name === action.name)){
return state;
}
else {
return state.concat({ name: action.name, info: action.info });
}
That should work. Also, I had to download the code at github.com/bethwickerson to understand the challenge you were facing and a suggestion: you don't need the .cache folder and node_modules committed to git. You can add those to .gitignore and then also run git rm -r --cached node_modules to remove it from git cache. Hope that helps!
That did it! I cannot possibly thank you enough. I would have never thought to code that myself like that, and kudos to you for finding my repo, as you can see it is for a good organization. I learned a ton from your posts, I really appreciate you taking the time to solve this issue for me. And thank you for the suggestion on the .gitignore, I had thought I added node_modules but I forgot the ending /
This has helped so much!
You are welcome. Glad I could help!
"As opposed to state in class components, useState does not work with object values." - Is this accurate?
Wondering if I misunderstood that statement as I believe, the following post has a working example of using object value instead
dev.to/reedbarger/react-hooks-chea...
Thanks for pointing that out. The verbiage is incorrect. It does work with object values, but primitives can be used as well and it is the preferred way of using it unless the values in the object are related. I will update the post to reflect the same.
You are great ... From few days I was scratching my head to solve this issue and you have solve in just a second ❤️😌😍😍
Happy to hear that it helped!