React Native UI Component Not Updating when Redux Store Changes

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Having trouble getting your React Native UI components to update after the state of your Redux store has changed? Your problem is likely related to the brave new world of ES6 and the Functional Programming Paradigm. Specifically, in your Redux reducers you need to make sure you are keeping everything “immutable”. The simplest way to fix this if the spread operator (…) isn’t working for you is to try wrapping values that you wish to copy in JSON.parse and JSON.stringify methods. I know it’s very ugly, but it is an extremely effective method for fixing issues with React, Redux, and UI components that are failing to sync with state changes in your Redux store. For example, take a look at the two reducers below. The first example shows a broken reducer from one of my applications. And the second example shows the same reducer after I fixed it using the method described above:

Broken Reducer

const initialState = {
snacks: []
}
const logCaloriesReducer = (state, action) => {
// check for state undefined to prevent
// redux from crashing app on load
if (typeof state === 'undefined') {
return initialState;
}
switch(action.type) {
case 'LOG_CALORIES':
const updatedState = { ...state };
const indexOfNextSnack = updatedState.snacks.length;
const newSnack = {
calories: action.payload.calories,
time: action.payload.time
};
updatedState.snacks[indexOfNextSnack] = newSnack;
return updatedState;
default:
return state;
return state;
}
};

Working Reducer

const initialState = {
snacks: []
}
const logCaloriesReducer = (state, action) => {
// check for state undefined to prevent
// redux from crashing app on load
if (typeof state === 'undefined') {
return initialState;
}
switch(action.type) {
case 'LOG_CALORIES':
const newState = JSON.parse(JSON.stringify(state));
const indexOfNextSnack = state.snacks.length;
const newSnack = {
calories: action.payload.calories,
time: action.payload.time
};
newState.snacks[indexOfNextSnack] = newSnack;
return newState;
default:
return state;
return state;
}
};
 

topherPedersen