Common modifications for all actions in reducer - reactjs

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);
};

Related

How can i save many objects in Redux?

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],
};
}

What are the pros and cons of using a single action to modify multiple values, or an action for each value? Why?

I'm trying to find what would be the best pattern to manage my reducers.
I have the following page:
I know I could've used redux-forms for this, but this is not the point since I only used these fields/form as an example.
We have multiple ways of handling this on redux:
1: having a single action to update those fields values based on the input's name property:
const UPDATE_VALUES = 'UPDATE_VALUES';
const INITIAL_STATE = {
aString: '',
setOfValues1: [],
setOfValues2: []
};
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case UPDATE_VALUES: {
if (action.name === 'setOfValues1' || action.name === 'setOfValues2') {
const array = [...state[action.name]];
array.push(action.value);
return {
...state,
[action.name]: array
};
}
return {
...state,
[action.name]: action.value
};
}
default:
return state;
}
};
2: having multiple actions to each field value:
const UPDATE_A_STRING = 'UPDATE_A_STRING';
const UPDATE_SET_1 = 'UPDATE_SET_1';
const UPDATE_SET_2 = 'UPDATE_SET_2';
const INITIAL_STATE = {
aString: '',
setOfValues1: [],
setOfValues2: []
};
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case UPDATE_A_STRING:
return {
...state,
aString: action.value
};
case UPDATE_SET_1: {
const array = [...state.setOfValues1];
array.push(action.value);
return {
...state,
setOfValues1: array
};
}
case UPDATE_SET_2: {
const array = [...state.setOfValues2];
array.push(action.value);
return {
...state,
setOfValues2: array
};
}
default:
return state;
}
};
and more ways that I'm not aware of.
what would be the good practice/best pattern in this case? Where can I look for, to learn more patterns to situations like these and other situations as well?
What about this?
const UPDATE_VALUES = 'UPDATE_VALUES';
const INITIAL_STATE = {
aString: '',
setOfValues1: [],
setOfValues2: []
};
const setOfValues = ['setOfValues1', 'setOfValues2'];
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case UPDATE_VALUES: {
if (setOfValues.includes(action.name)) {
return {
...state,
[action.name]: state[action.name].concat(action.value);
};
}
return {
...state,
[action.name]: action.value
};
}
default:
return state;
}
};

How can I update the state of reducer?

I want to update the state of activitiesData when ACTIVITIES_SEND_SUCCESS is executed by appending the new data to the end of the object activitiesData.
ActivitiesReducer.js
import {
ACTIVITIES_FETCH_SUCCESS,
ACTIVITIES_SEND_SUCCESS,
SUBACTIVITY_SEND_SUCCESS
} from '../actions/types';
const INITIAL_STATE = { activitiesData: {}, activityCreated: {}, listActivity: {} };
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ACTIVITIES_FETCH_SUCCESS:
return { ...state, activitiesData: action.payload };
case ACTIVITIES_SEND_SUCCESS:
return { ...state, activityCreated: action.payload };
case SUBACTIVITY_SEND_SUCCESS:
return { ...state, listActivity: action.payload };
default:
return state;
}
};
You can append the data using spread operator syntax like
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ACTIVITIES_FETCH_SUCCESS:
return { ...state, activitiesData: action.payload };
case ACTIVITIES_SEND_SUCCESS:
return { ...state, activityCreated: action.payload, activitiesData: {...state.activitesData, ...action.payload } };
case SUBACTIVITY_SEND_SUCCESS:
return { ...state, listActivity: action.payload};
default:
return 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;
}
}

My redux reducers all look the same. Am I doing it wrong?

I'm building a quite simple app using Redux and my reducers all look alike. It works, technically, but that's a lot of code duplication.
// The employees reducer
export default (state = initialState, action) => {
switch (action.type) {
case EMPLOYEES_REQUEST:
return [ ...state, { isFetching: true } ]
case EMPLOYEES_SUCCESS:
// DEBUG
console.log('Dispatching employees');
console.log(action.response);
// END DEBUG
// Return employees directly in the employees state
return { ...state, list: JSON.parse(action.response) };
case EMPLOYEES_FAILURE:
return [ ...state, { isFetching: false } ]
default:
return state
}
}
And
// The services reducer
export default (state = initialState, action) => {
switch (action.type) {
case SERVICES_REQUEST:
return [ ...state, { isFetching: true } ]
case SERVICES_SUCCESS:
// DEBUG
console.log('Dispatching services');
console.log(action.response);
// END DEBUG
// Return services directly in the services state
return { ...state, list: JSON.parse(action.response) };
case SERVICES_FAILURE:
return [ ...state, { isFetching: false } ]
default:
return state
}
}
Is there something I can to to use a generic reducer with different actions?
Thanks!
Reducer is just a function. You could always use a higher order function to make it.
const makeListReducer = (initial, prefix) => (state = initial, action) => {
switch(action.type) {
case `${prefix}_REQUEST`: return {...state, isFetching: true}
case `${prefix}_SUCCESS`: return {...state, isFetching: false, list: JSON.parse(action.response)}
case `${prefix}_FAILURE`: return {...state, isFetching: false, /*etc*/}
}
return state
}
// The employees reducer
export default makeListReducer(initialState, 'EMPLOYEES')

Resources