The reason I'm asking is simple, the user can't log out because redux's store is still holding references to RealmObject
instances that have already been deleted.
The user is presented with the following error as described in Realms issue 1031
I'm using the following packages that are related to the issue:
- "react-native": "^0.46.1"
- "react-navigation": "^1.0.0-beta.11"
- "react-redux": "^5.0.5"
- "realm": "^1.9.0",
- "redux": "^3.7.0",
- "redux-logger": "^3.0.6",
- "redux-persist": "^4.8.2",
- "redux-thunk": "^2.2.0"
Now, I have a few actions and reducers in which redux's store is updated. When the user decides to nuke it all, I perform the following dance:
static logout() {
try {
// Remove everything from database
RealmInstance.write(() => {
RealmInstance.deleteAll();
});
} catch (ex) {
if (__DEV__) {
console.log(`Logout failed: ${ex.message}`);
}
return false;
}
return true;
};
The following function dispatches the result
export function logoutUser() {
return dispatch => {
if (Account.logout()) {
dispatch(logoutSuccess());
} else {
dispatch(logoutError());
}
}
}
And for every reducer, I reset the state to it's initial state: e.g. for the account reducer
export function accountReducer(state = { user: Account.User }, action) {
switch (action.type) {
case Types.SET_USER:
case Types.GET_USER:
case Types.LOGIN_USER_SUCCESS:
case Types.LOGIN_USER_ERROR:
return state; // for example
case Types.LOGOUT_USER:
return {
...initialUserState,
loggedOut: action.loggedOut,
};
default:
return state // for example
}
}
For the navigation reducer, I reset the routes and point to the login page. This is where it starts all over again.
function nav(state = initNavState, action) {
let nextState = null;
// if (...) { ...
} else if (action.type === 'LOGOUT_USER') {
nextState = AppNavigator.router.getStateForAction(NavigationActions.reset(
{
index: 0,
key: null,
actions: [ NavigationActions.navigate({
routeName: 'Login'
}) ]
}
))
} else {
nextState = AppNavigator.router.getStateForAction(action, state);
}
// Simply return the original `state` if `nextState` is null or undefined.
return nextState || state;
}
If I am correct, the issue exists because you call dispatch (redux's middleware/thunk logic) to spread the word throughout the application. But as far as I understand, dispatch invokes parts of the store that still holds references to the already deleted RealmObject
instances. Hence the error.
Somewhere far down in the stacktrace, it points to dispatch(logoutSuccess());
.
Is there another approach I should be using? I need the reducers to reflect on the logout command so their states are reset before the dispatcher is invoked.