I have a FlatList
component that uses Redux (indirectly) as the source for the data
prop. See below
const mapStateToProps = state => ({
rdx_activeUsers: state.profile.activeUsers,
});
convertRdxActiveUsersObjectToUsableArray = () => {
let activeUsersArray = [];
Object.values(this.props.rdx_activeUsers).forEach(userObj => {
activeUsersArray.push(userObj);
});
return activeUsersArray;
};
//-----------------------------------------------------------------------
render() {
let usableArray4FlatList = this.convertRdxActiveUsersObjectToUsableArray();
return (
<View>
<FlatList
data={usableArray4FlatList}
Whenever an active user is added or removed in Firebase DB, I have listeners that increase or reduce the size of the Redux object rdx_activeUsers
.......the goal is that this change in Redux should trigger the render()
function (due to Redux being used in the convertRdxActiveUsersToUsableArray
function....which is present in the render()
function).
I can see via debugging tool that Redux rdx_activeUsers
object is updating correctly whenever I add or remove a user....however the FlatList only rerenders dynamically when I add a user (i.e. the Redux object rdx_activeUsers
increases in size)...but not when I remove one (i.e the Redux object rdx_activeUsers
decreases in size).
I also tried adding prop extraData={this.props.rdx_activeUsers}
...but this didnt make any difference
UPDATE AS OF 12/31
Below are my reducers......
case ACTIVE_USER_CHILD_ADDED
is successfully updating Redux AND triggering the rerender
case ACTIVE_USER_CHILD_REMOVED
is successfully updating Redux BUT NOT triggering the rerender....looks like thats where the issue is
case ACTIVE_USER_CHILD_ADDED:
const key2Add = action.payload.userId;
const val2Add = action.payload;
return { ...state, activeUsers: { ...state.activeUsers, [key2Add]: val2Add } };
case ACTIVE_USER_CHILD_CHANGED:
const key2Updel = action.payload.userId;
const val2Updel = action.payload;
if (val2Updel.active) {
return { ...state, activeUsers: { ...state.activeUsers,[key2Updel]: val2Updel } };
}
if (state.activeUsers) {
const updatedstate = state;
delete updatedstate.activeUsers[key2Updel];
return {...updatedstate};
}
//else
return state;
case ACTIVE_USER_CHILD_REMOVED:
const key2Del = action.payload.userId;
const oldState = state;
delete oldState.activeMsgUsers[key2Del];
return {...oldState};
Below shows my action creators
export const _actActiveUserChildAdded = userObj => {
return {
type: ACTIVE_USER_CHILD_ADDED,
payload: userObj,
};
};
export const _actActiveUserChildChanged = userObj => {
return {
type: ACTIVE_USER_CHILD_CHANGED,
payload: userObj,
};
};
export const _actActiveUserChildRemoved = userObj => {
return {
type: ACTIVE_USER_CHILD_REMOVED,
payload: userObj,
};
};
CodePudding user response:
try this
const mapStateToProps = state => ({
rdx_activeUsers: state.profile.activeUsers,
});
//-----------------------------------------------------------------------
render() {
let activeUsersArray = [];
Object.values(this.props.rdx_activeUsers).forEach(userObj => {
activeUsersArray.push(userObj);
});
return (
<View>
<FlatList
data={activeUsersArray}
CodePudding user response:
This piece of code does not trigger a rerender
case ACTIVE_USER_CHILD_REMOVED:
const key2Del = action.payload.userId;
const oldState = state;
delete oldState.activeMsgUsers[key2Del];
return {...oldState};
By returning {...oldState}
all the references inside this.state
stay the same, and no update is triggered
fast solution
Put return {...oldState, activeMsgUsers: {...activeMsgUsers}}
instead
better solution
Don't use delete
, use Array.filter
instead to create a new object reference
best solution
Refactor your conponent to hooks and make activeMsgUsers
a standalone state, if you do it correctly, calling setActiveMsgUsers
returning the destructured old state you cannot have that problem
CodePudding user response:
change case ACTIVE_USER_CHILD_REMOVED
like following it should work, you tried modifying the object which was mutating the state object instead of returning a new object.
case ACTIVE_USER_CHILD_REMOVED:
const key2Del = action.payload.userId;
const {activeUsers:{[key2Del]:_,...restActiveUsers}} = state;
return {...state,activeUsers:{...restActiveUsers}};