Reputation: 375
I have been trying to write some codes in redux reducers where the logics of state updating are similar. My initial state looks like this:
const initialState = {
isLoading: false,
events: [
{
year: 2021,
place: [
{
id: 1,
name: "BD",
address:[{id:1,text:"test"}]
},
{
id: 2,
name: "BD Test"
address:[{id:5,text:"test one"}]
}
]
}
]
};
And, I have updated the state in reducer like this:
...state,
events: state.events.map((event) => ({
...event,
place: event.place.map((place) => {
const address = place.address.find((x) => x.id === action.addressId);
if (address) {
return {
...place,
address: place.address.map((el) => {
if (el.id === action.addressId) {
return { ...el, isChanged:true };
}
return { ...el, isChanged:false };
}),
};
}
return place;
}),
})),
I have been using this logic similarly in couple of places where i have just added some extra property like in this case "isChanged:true" and "isChanged:false"
. This portion of coded seems repetitive So, I have tried to write the utility function like this so far:
const updateAddress = (years, addressId, update) => years.map((year) => ({
...year,
place: year.place.map((place) => place.address.find((el) => el.id === addressId)
? {
...place,
address: place.address.map(
(el) => el.id === addressId ? update(x) : x
),
}
: place),
}));
This utility function works fine but it only updates work when el.id === addressId
becomes true
and add only isChanged:true
. But, I need to add also isChanged:false
to other addresses just like the logic written in the reducer.
Can anybody help with this how can I make that function works accordingly or is there any other options can I follow to move that logic to a utility function.
Thanks in Advance.
Upvotes: 0
Views: 146
Reputation: 1877
If I would follow your implementation of this "utility function", the solution is simple. In your original implementation, this:
place.address.map((el) => {
if (el.id === action.addressId) {
return { ...el, isChanged:true };
}
return { ...el, isChanged:false };
}
is this (in more clean and readable way):
place.address.map((el) => {
let newElState;
if (el.id === action.addressId) {
newElState = { ...el, isChanged:true };
} else {
newElState = { ...el, isChanged:false };
}
return newElState;
}
Hence, you are doing 2 things:
So, you need to pass another updater as an argument of your utility function:
const updateAddress = (years, addressId, updateId, updateOthers) => years.map((year) => ({
...year,
place: year.place.map((place) => place.address.find((el) => el.id === addressId)
? {
...place,
address: place.address.map(
// this arrow function works in the same way as the code snippet above:
// 1. if an address in the place.address arrray has the same id
// as id passed in addressId, the callback updateId will be called
// 2. if an address in the place.address arrray does not have the same id
// as id passed in addressId, the callback updateOthers will be called
//
// what really updateId, or updateOthers do depends on their implementation,
// what the caller of updateAddress put as the third and the fourth argument
(el) => el.id === addressId ? updateId(el) : updateOthers(el)
),
}
: place),
}));
Upvotes: 1