How can i save many objects in Redux? - reactjs

I get a lot of objects in redax, but only the last one is saved. Each new object replaces the previous one. Can you please tell me how can I save all the objects at once?
I have redux like this
My Reducer
const initianalState = {
};
export const WorldReducer = (state = initianalState, action) => {
switch (action.type) {
case LOAD_PLANET_NAME: {
return {
...state,
homeworld: action.data,
};
}
default: return state;
}
};
My action
export function loadPlanetName(data) {
return {
type: LOAD_PLANET_NAME,
data
};
}

i think it will solve the problem
case LOAD_PLANET_NAME: {
return {
...state,
homeworld: [...state.homeworld,action.data],
};
}

Related

How to useDispatch async multiple times?

I am using useDispatch two times to change my todos and then change my login status. Both work seperately but when put after each other the second dispatch overwrites my list of todos to an empty object [].
How would I make this work?
Axios Post
axios
.post("http://localhost:3333/user/login", newUser)
.then((response) => {
//do stuff
dispatch(changeTodos(stuff));
dispatch(login());
});
Actions
export const login = (data) => {
return {
type: "LOGIN",
data: data,
};
};
export const changeTodos = (data) => {
return {
type: "CHANGETODOS",
data: data,
};
};
Reducer
const loggedReducer = (state = false, action) => {
switch (action.type) {
case "LOGIN":
return true;
case "LOGOUT":
return false;
default:
return false;
}
};
export default loggedReducer;
const todosReducer = (state = [], action) => {
switch (action.type) {
case "CHANGETODOS":
return action.data;
default:
return [];
}
};
export default todosReducer;
For your default you need to return state otherwise it's gonna hit the default when it doesn't match the action type. For example, LOGIN is will make your TodosReducer return [] which is why it's being cleared out.
default:
return state;

React/Redux - list not updating after a list item is editted

I Have a list of objects being displayed in a table.
When an item in the list is edited, the updated item is not displayed unless I refresh the page.
REDUCER FOR LIST
export const eaCodesReducer = (state = initialState.eaCodes, action) => {
switch (action.type) {
case "GET_EA_CODES": {
return {
...state,
eaCodes: action.payload
}
}
default: {
return state
}
}
}
REDUCER FOR SINGLE ITEM
export const eaSingleEaCodeReducer = (state = initialState.eaCode, action) => {
switch (action.type) {
case "UPDATE_EA_CODE": {
return {
...state,
eaCode: action.payload
}
}
default:
return state
}
}
How do I then tell it to update the eaCodes list to incorporate the single item change?
export const eaSingleEaCodeReducer = (state = initialState.eaCode, action) => {
switch (action.type) {
case "UPDATE_EA_CODE": {
return {
...state,
eaCode: action.payload,
eaCodes: [...state.eaCodes, action.payload]
}
}
default:
return state
}
}
Your eaCodesReducer should return an array instead of an object. So the new state is always the previous items in the array along with the new one and you should map over this piece of state in your component which is bound to your store. The update in the table should reflect automatically when this particular piece of state is updated in your store.
// this should be an array also
export const eaCodesReducer = (state = initialState.eaCodes, action) => {
switch (action.type) {
case "GET_EA_CODES": {
// should be an array
return [
...state,
action.payload
]
}
default: {
return state
}
}
}
Hope this helps !
#D10S had the right idea, but resulted in the app crashing. Instead of adding the extra reducer - i updated the action to call the reducer if the initial put request is successful:
export const updateEnforcementActionCode = (id, updateTypeObj) => {
return dispatch => {
return axios.put(`/api/enforcementactions/codes/${id}`, updateTypeObj)
.then(res => {
dispatch({ type: "UPDATE_EA_CODE", payload: res.data })
if (res.status === 200) {
return axios.get('/api/enforcementactions/codes')
.then(res => {
dispatch({ type: "GET_EA_CODES", payload: res.data })
})
}
}).catch(err => {
dispatch({ type: "GET_ERRORS", payload: err.response.message })
})
}
}
This does seem a little redundant. If anyone has a suggestion to make this slicker I'm open.

Common modifications for all actions in reducer

So here is the problem, I need some modifications to always to be done after each and every action except one. So in order to achieve this I have done the following. Is there a better way to achieve this?
export const reducer = (state, action) => {
switch (action.type) {
case 'AddCheckboxJson': {
return ReducerWrapper({ ...state,objCheckBox:action.payload });
}
case 'insertAt':return ReducerWrapper({
...state,objCheckBox:{...state.objCheckBox,
Values:insertAt(action.payload.index,action.payload.entry,"iDisplayOrder",state.objCheckBox)
}
})
case 'INSERT_ABOVE':
return ReducerWrapper({
...state, objRadio: {
...state.objRadio,
Values: action.payload
}
})
case 'INSERT_BELOVE':
return ReducerWrapper({
...state, objRadio: {
...state.objRadio,
Values: action.payload
}
}),
case 'REPLACE':return { ...action.payload }
default: {
return state;
}
}
};
Here the function ReducerWrapper does the common modification
export const ReducerWrapper = State => {
return {...State,
//modifications done here
}
}
This is really a lot simpler than it probably seems, just return for the two scenarios you don't want to apply the additional state i.e.
export const reducer = (state, action) => {
switch (action.type) {
case 'AddCheckboxJson': {
state = {
...state,
objCheckBox: action.payload
};
}
case 'insertAt': {
state = {
...state,
objCheckBox:{
...state.objCheckBox,
Values: insertAt(
action.payload.index,
action.payload.entry,
"iDisplayOrder",
state.objCheckBox
)
}
}
}
case 'INSERT_ABOVE': {
state = {
...state,
objRadio: {
...state.objRadio,
Values: action.payload
}
}
}
// presumably this should be INSERT_BELOW?
case 'INSERT_BELOVE': {
state = {
...state,
objRadio: {
...state.objRadio,
Values: action.payload
}
}
},
// return the state early in both these scenarios
case 'REPLACE': return { ...action.payload }
default: return state;
}
// run additional state change
return ReducerWrapper(state);
};

How to add data to redux state array without any id in a reducer?

I've got this reducer :
import { GET_CHAT, ADD_MESSAGE } from '../actions';
export default function (state = null, action) {
switch (action.type) {
case GET_CHAT:
return { ...state, [action.meta.id]: action.payload.data };
case ADD_MESSAGE:
console.log(state[action.meta.convId].chat.messages)
return {
...state,
[action.meta.convId]: {
...state[action.meta.convId],
chat: {
...state[action.meta.convId].chat,
messages: {
...state[action.meta.convId].chat.messages,
action.payload
}
}
}
};
default:
return state;
}
}
Where I want to add the action.payload to the end of the messages array. The issue is : when I try to put a key to the payload like so :
[action.meta._id]:action.payload
Messages is not an array anymore but becomes an object. So i can't loop over it anymore with map(). And redux won't let me push the payload directly to the array, it seems like i must put a key ...
Any help would be appreciated, thank's :)
If you want your messages to always be an array then your reducer should be like below:
import { GET_CHAT, ADD_MESSAGE } from '../actions';
export default function (state = null, action) {
switch (action.type) {
case GET_CHAT:
return { ...state, [action.meta.id]: action.payload.data };
case ADD_MESSAGE:
console.log(state[action.meta.convId].chat.messages)
return {
...state,
[action.meta.convId]: {
...state[action.meta.convId],
chat: {
...state[action.meta.convId].chat,
messages: [ //USE SQUARE BRACKETS INSTEAD
...state[action.meta.convId].chat.messages,
action.payload
]
}
}
};
default:
return state;
}
}

how to push an object into array using react

This is my initial state constant object, I'm trying to add a new comment items into comments but this code which is not pushing my object into it where i'm doing wrong thanks in advance.
export const comments = [];
export const BlogPostReducer = (state = comments, action) => {
switch (action.type) {
case 'ADD_COMMENT':
return [
...state,
{
name: action.comment.name,
subject: action.comment.subject,
message: action.comment.message
}
];
default:
return state;
}
};
after i used see console here...still im getting empty state
image here
For pushing new object you need to do as
return [
...state,
{
name: action.comment.name,
subject: action.comment.subject,
message: action.comment.message
}
];
This will create and new array, push the object in it and return it
If you want to add it to an array in the immutable way, you should use 'concat'
try below code.
export const comments = [];
export const BlogPostReducer = (state = comments, action) => {
switch (action.type) {
case 'ADD_COMMENT':
return state.concat({name: action.comment.name,subject: action.comment.subject,message: action.comment.message});
default:
return state;
}
};
This way i have achieved,
const addCommentToArray = (state, action) => {
return [...state.comments, {
name: action.comment.name,
subject: action.comment.subject,
message: action.comment.message
}];
}
export const BlogPostReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_COMMENT':
return Object.assign({}, state, { comments: addCommentToArray(state, action) });
default:
return state;
}
};
You need to pass comment to store as argument and append to comments.
export const BlogPostReducer = (state, action) => {
switch (action.type) {
case 'ADD_COMMENT':
let { comments } = state;
comments = comments || [];
comments.push(action.comment);
state.comments = comments;
return state;
default:
return state;
}
};

Resources