Immutable remove object entry react reducer - reactjs

I want to immutable remove an object entry in react reducer
obj = {
selections: {}
}
this is how i add things to my selections obj
return {
...state,
selections: {
...state.selections,
[action.data.type]: action.data
}
};
this will give me
selections: {
test: { some funky data }
}
then when i want to remove test? How do i accomplish that?

Maybe something like this,
this.setState(state => {
return {
...state,
selections: {
...state.selections,
selections: delete state.selections.test
}
}
})

The best i could do for now is to set it to null
return {
...state,
selections: {
...state.selections,
[action.data.type]: null
}
};
its not firing the update when i use Object.assign and using delete

Just copy your state to a temporal variable, then delete the that you don't want:
//...
case 'REMOVE_PROPERTY':
//here we make a copy of selection object, note that this is a shallow copy
let newSelections = { ...state.selection };
delete newSelections[action.data.type];
return {
...state,
//here we overwrite selections object on a new created object before returning the value
selections: newSelections
};
//...

Related

how to update a specific value in an object in redux

My Reducer :
function updatePersonDetailsReducer (state = {
updatePersonDetails: {
name: "John",
id: "3ery4",
address: "somewhere on earth"
}
}, action) {
switch (action.type) {
case C.UPDATE_PERSON_DETAILS: {
return {
...state
,updatePersonDetails :action.payload
}
}
default : {}
}
return state
}
I called this way in my component,
this.props.dispatch(updatePersonDetails({name:Variant.objValue.name,id:Variant.objValue.Id}))
But this seems to, create a new array than overwriting the values in the current array (updatePersonDetails) in reducer.
You can spread your object and do it like this.
case C.UPDATE_PERSON_DETAILS: {
return {
...state,
updatePersonDetails :
{...state.updatePersonDetails,...action.payload}
}
}
This will keep your old keys there and will only update the newly added keys.

Unable to filter data in Redux Reducer

I'm trying to create a reducer for a ToDo App where i have successfully managed to create an Add reducer but somehow i'm unable to filter data on the basis of the ID suppose my ID is 1 then if there is a ToDo Bucket(bucket is basically a parent where i'm creating ToDo's) then get that ToDo bucket data.
In Redux dev tools i have checked it is showing me a infinite hierarchical tree of filteredData object. but not showing directly the Bucket ID 1 data and same with delete reducer as well. Can someone please help in highlighting what exactly wrong i'm doing or missing.
case EDIT_TODO_BUCKET: {
return (
{
...state,
data: {
...state.data,
[action.payload.id]: {
...state.data[action.payload.id],
filteredData: state.data[action.payload.id]
}
}
}
)
}
case DELETE_TODO_BUCKET: {
return (
{
...state,
data: {
...state.data,
[action.payload.id]: {
...state.data[action.payload.id],
}
}
}
)
}
case DELETE_TODO_BUCKET: {
return (
{
...state,
data: {
...state.data,
[action.payload.id]: {
...state.data[action.payload.id],
}
}
}
)
}
^ Read this It doesn't do anything at all except create a new reference each time.
I imagine you might want the following:
return {
...state,
// removes the key of action.payload.id from the state.data
data: Object.entries((acc,[key,value]) => key === action.payload.id ? acc : ({...acc,[key]:value}),{})
}

Updating a single value for each item in object in Redux State

I have a list of notifications inside redux state. As you can see below.
There could be more items in the list, and my goal is to set isRead value to true for all items in the list depending on the isDiscussionType value. I am using the following code in the reducer:
case MARKALLASREAD_NOTIFICATIONS_SUCCESS:
return {
...state,
loading: false,
notifications:
Object.keys(state.notifications).map(id => {
if (state.notifications[id].isDiscussionType == action.payload.isDiscussionType)
return { ...state.notifications[id], isRead: true }
else
return { ...state.notifications[id] }
})
};
This code results in the following state, where the key is lost (set to 0), and the isRead value is not changed (although the database is updated correctly).
Do you see any problems in the code I shared above?
Map returns an array instead of an object. That is why you lose your id, since the 0 is just the index within the array, which is now under notifications. I would move the generation of notifications out of the return to get more flexibility:
case MARKALLASREAD_NOTIFICATIONS_SUCCESS:
const notifications = { ...state.notifications }
Object.values(notifications).forEach(notification => {
if(notification.isDiscussionType === action.payload.isDiscussionType) {
notifications[notification.id] { ...notification, isRead: true }
}
}
return {
...state,
loading: false,
notifications
};
This will return an immutable object with each notification changed, if the isDiscussionType are the same. Because map, filter, reduce return arrays, I would move it out of the return and use forEach.
Hope this helps. Happy coding.
If your notifications is a list i.e. an array, you shouldn't use Object.keys on it, and go straight with the map:
case MARKALLASREAD_NOTIFICATIONS_SUCCESS:
return {
...state,
loading: false,
notifications: state.notifications.map(notification => {
if (notification.isDiscussionType === action.payload.isDiscussionType) {
return {
...notification,
isRead: true
}
} else {
return notification;
}
})
};

Delete an element from array using redux

I am trying to make a todo app using redux and I'm stack on how to delete a todo from the array.
reducer.js
export default function todo(state, action) {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
id: action.id,
text: action.text,
completed: false
}
case 'REMOVE_TODO':
return {
id: action.id,
...state.slice(id, 1)
}
default:
return state;
}
}
action.js
let nextTodoId = 0
export const addTodo = text => ({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
export const removeTodo = id => {
type: 'REMOVE_TODO',
id
}
So far i can add and toggle a todo as completed or not. Thanks
Using redux you need to return all array elements except the removed one from reducer.
Personally, I prefer using the filter method of the Array. It'll return you a shallow copy of state array that matches particular condition.
case 'REMOVE_TODO':
return state.filter(({id}) => id !== action.id);
In react redux application, you should know, you always have to create a new object,
to deleting an item please use spread operator like this :
return [...state.filter(a=>a.id !== id)]

Updating an item in Redux using ImmutableJS given a key

Redux State:
let initialState = Immutable.fromJS({
budgetItems: [],
editingBudget: [[]]
});
Trying to update items in the budgetItems section, which is an array of objects.
The structure of the objects in the array is like:
let initBudget = {budgetCategory: '', budgetCost: '', budgetDate: ''};
My attempt:
case types.UPDATE_EXISTING_BUDGET:
return state.getIn(['budgetItems']).update(
state.getIn(['budgetItems']).findIndex(function(item) {
return item.get("budgetCategory") === action.payload.budgetCategory;
}), function(item) {
return item.set(action.payload.budgetCategory);
}
);
Trying to literally replace the entire object that I've found. The above code is working if I set a single key with a value, but not the entire object
To update an object or an array you'll need the updateIn method.
import { fromJS, List, Map } from immutable;
const initialState = fromJS({
data: List([Map({ foo: { bar: baz } } })],
});
functionFooReducer(state = initialState, action) {
switch (action.type) {
case UPDATE:
return state
.updateIn(['data.0.foo.bar'.split('.')], (), action.value);
// ...
}
}

Resources