I have this userData state which I use to render a list of notifications - an array of objects - from the user. On the list I've a delete button for each notification which calls a function to handle the update of userData, and remove the notification inside the array to set it's new state. In the end it updates the state with correct data, but on the template it never gets update, in fact it appears to understands that the array is empty... (?).
Instead of entering this if userData.notifications && userData
... it enter in the else.
//* const Notifications = () => { **/
//* ... **/
const [userData, setUserData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
// handles delete
const deleteNotifications = (notificationId) => {
setIsLoading(true);
const user = {...userData};
let newUserData = [];
if(notificationId) {
newUserData = user.notifications.filter(notification => {
return notification.notificationId !== notificationId;
});
} else {
user.notifications = [];
newUserData = user;
}
setUserData(newUserData);
setIsLoading(false);
}
// template
const renderNotifications = () => {
if(userData.notifications && userData.notifications.length) {
return (
<>
{ userData?.notifications?.map(({
notificationId,
sendedAt,
body,
}) => (
<NotificationShadow key={notificationId}>
<SwipeableView onPress={() => deleteNotifications(notificationId)}>
<Notification>
<NotificationHeader>
<NotificationText>Nome da Notificação</NotificationText>
<NotificationText>{sendedAt}</NotificationText>
</NotificationHeader>
<ShowMoreText
text={body}
numberOfLines={2.6}
textColor={'#474747'}
/>
</Notification>
</SwipeableView>
</NotificationShadow>
))}
{ userData.notifications.length ?
<DeleteAllContainer onPress={() => deleteNotifications()}>
<DeleteAllIcon
type="font-awesome-5"
name="trash"
solid
/>
</DeleteAllContainer> : null }
</>
);
} else {
return (
<EmptyDataText>Sem notificações</EmptyDataText>
);
}
}
return (
<StickyHeader title="Notificações">
<NotificationsContainer>
{
isLoading ? <Text>loading...</Text> :
renderNotifications()
}
</NotificationsContainer>
<AndroidBackHandler onBackPress={() => true} />
</StickyHeader>
);
//* } **/
I tried to create a state of notification field that belongs to userData object, but it hasn't work. I had also inserted the renderNotifications code directly on the final template return, but... no results.
CodePudding user response:
You were modifying the "shape" of your userData
, this should fix it:
const deleteNotifications = (notificationId) => {
setIsLoading(true);
let newNotifications = [];
if (notificationId) {
newNotifications = userData.notifications.filter((notification) => {
return notification.notificationId !== notificationId;
});
}
setUserData({...userData, notifications: newNotifications});
setIsLoading(false);
};
CodePudding user response:
For starters, the declaration of userData
concerns me.
Lets try to set the initial state to the same type as future states:
const [userData, setUserData] = useState([]);
I am assuming you have something in the beginning of the function that sets the state of userData
. But since you added the notification object, the function for delete instead updates userData
not with the new data, but with only notifications. This would cause future notifications to not exist, thus creating and empty array.
I also don't think that user
is all that useful here, since it is just a copy where you read the data from userData
, which can also be read from userData
without the extra step.
Lets try applying the changes:
if(notificationId && userData) {
newUserData = userData.filter((user) => {
return userData.notification.notificationId !== notificationId;
});
}
If this (with some minor tweaks on your end) doesn't work, you would definitely need to provide more details, especially on the details of your states.