Updating State for changed item not displaying on react frontend - reactjs

I am working on my reducer and I am trying to get the case for UPDATE working.
I am just trying to update the list on my react frontend when a certain object ID changes in the state. How can I make it so the item with a certain ID changes on the frontend in this reducer.
I tried this in UPDATE_ANIMALS, but no luck
case 'UPDATE_ANIMALS':
return [
...state, item => item.id === action.payload.id ? action.payload : item
];
Below is my entire reducer.
export const ANIMALSReducer = (state = [], action) => {
switch (action.type) {
case 'FETCH_ANIMALS':
return action.payload;
case 'ADD_ANIMALS':
return [...state, action.payload];
case 'DELETE_ANIMALS':
return [
...state.filter(item => item.id !== action.payload)
];
case 'UPDATE_ANIMALS':
return [
NOT SURE WHAT TO PUT HERE
];
default:
return state;
}
};

You can achieve that very easily using the map function, basically you're generating a new array and the matching item given your payload will be updated with the payload instead the original:
case 'UPDATE_ANIMALS':
return state.map(item => item.id === action.payload.id ? action.payload : item);

Related

unable to understand reducer function in react redux

this is my reducer function :
export default (posts = [], action) => {
switch (action.type) {
case FETCH_ALL:
return action.payload;
case LIKE:
return posts.map((post) => (post._id === action.payload._id ? action.payload : post));
case CREATE:
return [...posts, action.payload];
case UPDATE:
return posts.map((post) => (post._id === action.payload._id ? action.payload : post));
case DELETE:
return posts.filter((post) => post._id !== action.payload);
default:
return posts;
}
};
in
case CREATE:
return [...posts, action.payload];
what i have understood so far is that reducer function gets old state and new state . old state is represented by 'posts' and new state is represented by 'action.payload' ...now what i do not understand is that what is [...posts, action.payload] ?
what are those three dots ?
why there are square brackets ?
what does reducer function returns ?
what is happening here ?
i am a java programmer , i can't understand anything here
i have understood everything .
reducer function is getting two parameters (posts = [], action) :
first one is old state and the second parameter is action object which includes type and new data ...this reducer function returns a new state by adding my new data into old state
in this
case CREATE:
return [...posts, action.payload];
these ...three dots are spread syntax which can be understood completely by going to the following link given by chellappan in comment section :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
[]square brackets denote an array which is our new state.

How do I update a state in redux reducer?

reducers.js
this is my initialState
const initialState = {
transfusions: [],
};
Here is my Switch logic
export default function (state = initialState, action) {
switch (action.type) {
case GET_TRANSFUSIONS:
return {
...state,
transfusions: action.payload,
};
case ADD_TRANSFUSION:
return {
...state,
transfusions: [...state.transfusions, action.payload],
};
case UPDATE_TRANSFUSION:
console.log(action.payload)
return {
...state,
transfusions: state.transfusions.map(
(transfusion) => transfusion.id === action.payload.id ? {
...state,
transfusion: action.payload
} : transfusions
),
};
case DELETE_TRANSFUSION:
return {
...state,
transfusions: state.transfusions.filter(
(transfusion) => transfusion.id !== action.payload
),
};
default:
return state;
}
}
I updated in the backend successfully but how do I update the frontend. I tried this method it works but it always needs to refresh the page to show me the updated data.
transfusions: state.transfusions.map( is relying on the old state so it is always one step behind
You can modify your code to something like this:
const transfusionExists = state.transfusions.find(t => t.id === action.payload.id)
if(!transfusionExists) state.transfusions.push(action.payload)
return {
...state
),
};
Finally I solved my issue. I used this code:
case UPDATE_TRANSFUSION:
const transfusionsExisted = state.transfusions.filter(
(transfusion) => transfusion.id !== action.payload.id
);
return {
transfusions: [action.payload, ...transfusionsExisted],
};
I deleted the record I wanted to update first and then pushed the new record.
I hope it will help you if you are suffering as I suffered from this problem.

How to update 1 item in state with redux?

I have a reducer and trying to update 1 item in the statearray. It looks like this:
const players = (state = [{name:'John',nrGames:0,nrWins:0},{name:'Ed',nrGames:0,nrWins:0},{name:'Mark',nrGames:0,nrWins:0}], action) => {
switch (action.type) {
case 'ADD_PLAYER':
return [...state,{name:action.name}]
case 'ADD_WIN':
return [...state, action.name == 'bla' ? {nrWins:10} : {} ]
default:
return state;
}
};
export default players;
I am trying to figure out how to change the nrWins property for a certain name. So when ADD_WIN is dispatched with name='John' how to just update the John object and up the nrWins property with 1 and not the other objects in the state?
You need to .map over the players and when you find the one the action is describing create a new player with the updated number of wins. For readability I created a function called incWinForPlayer.
const incWinForPlayer = (name) => (player) => {
return player.name === name
? {...player, nrWins: player.nrWins + 1}
: player
};
const players = (state, action) => {
switch (action.type) {
case 'ADD_PLAYER':
return [...state, {name: action.name}]
case 'ADD_WIN':
return state.map(incWinForPlayer(action.name));
default:
return state;
}
};
export default players;
The "recommended" approach is to slice the old array up to the new item, concat it with the modified one, and concat it with the rest of the array.
Make sure that your action returns the whole new item, and the index you want to modify.
Something like:
case 'ADD_WIN':
return [
...array.slice(0, action.index),
action.item,
...array.slice(action.index)
];
Edit 1: source https://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html#inserting-and-removing-items-in-arrays

Changing an array in a reducer when an item has been deleted or updated in react/redux

I am using react/redux and have been looking at ways to update my array of posts in my reducer if a post is edited or deleted.
Is there a more simple way rather than doing something with creating an index function which finds the index of the post you are trying to delete/update, then returning the current state with the updated array using slice?
This is what I have so far in my reducer, I am kind of stuck:
import constants from '../constants';
const initialState = {
all: [],
sorted: [],
};
export default (state = initialState, action) => {
const newState = Object.assign({}, state);
switch (action.type) {
case constants.CREATE_OFFER:
newState[action.payload.id] = action.payload;
newState.all.unshift(action.payload);
return newState;
case constants.GET_OFFERS:
newState.all = action.payload;
return newState;
case constants.GET_OFFER:
newState[action.payload.id] = action.payload;
return newState;
case constants.EDIT_OFFER:
newState[action.payload.id] = action.payload;
return newState;
case constants.DELETE_OFFER:
newState[action.payload.id] = action.payload;
return newState;
case constants.SORT_OFFERS:
newState.sorted = action.payload;
return newState;
default:
return state;
}
};
Instead of :
newState[action.payload.id] = action.payload;
return newState;
You can use ES6 sytax :
return {...state, [action.payload.id]: action.payload.data};
i believe if you use Object as a app state rather than an array , it will be easy to update , delete all you need to do is use .mapKeys method of lodash library along with property you want to extract from your array (ideally 'id')
import _ from 'lodash';
return _.mapKeys(action.payload.data, 'id');
this will return :
{
'1': { id: 1,
title: 'Hello!',
},
'2': {
id: 2,
title: 'World'
}
}
You can read more Here
I think, everything is good, but it will be better to use es6 spread operator, your code will look more clear
case constants.CREATE_OFFER:
return {
...state,
all: state.all.concat(action.payload),
[action.payload.id]: action.payload
}
case constants.EDIT_OFFER:
return {
...state,
[action.payload.id]: action.payload,
all: state.all.map( item => item.id === action.payload.id?action.payload: item )
}
case constants.DELETE_OFFER:
const new = {
...state,
all: state.all.filter( item => item.id !== action.payload.id)
};
delete new[action.payload.id];
return new;
}

Redux shopping cart example

I'am trying to understand the example named "shopping cart" giving for redux :
https://github.com/reactjs/redux/tree/master/examples/shopping-cart
In this example you can add elements to your list of items, I tried to implement the function of remove a list of items :
But in the reducers folder there is an addedIds() function, I added a case to remove the element of the list but I don't know how to implement that, here is the function : the reste of my code is working fine I just don't know how to delete the product id from the array of addedIds.
const initialState = {
addedIds: [],
quantityById: {}
};
function addedIds(state = initialState.addedIds, action) {
switch (action.type) {
case ADD_TO_CART:
console.log("added ADD");
if (state.indexOf(action.productId) !== -1) {
return state
}
return [ ...state, action.productId ];
case REMOVE_TO_CART:
console.log("removed ADD");
// here is my problem
default:
return state
}
}
I assumed I need to do something like here :
Is this the correct way to delete an item using redux?
but I don't know how
Can you help me please ?
You can delete some element from array just filtering it out:
// ... skipped other cases from the switch
case REMOVE_TO_CART:
return state.filter(productId => action.productId !=== productId)
Approach with .filter() function looks very short and produces a new array instance as it required by redux.
For those who have a similar problem here is the solution :
const initialState = {
addedIds: [],
quantityById: {}
};
function addedIds(state = initialState.addedIds, action) {
switch (action.type) {
case ADD_TO_CART:
console.log("added ADD");
if (state.indexOf(action.productId) !== -1) {
return state
}
return [ ...state, action.productId ];
case REMOVE_TO_CART:
console.log("removed ADD");
return [ ...state.slice(0,state.indexOf(action.productId),
...state.slice(state.indexOf(action.productId)+1))
];
default:
return state
}
}
thanks to Josh Deeden who found this vidéo :
https://egghead.io/lessons/javascript-redux-avoiding-array-mutations-with-concat-slice-and-spread

Resources