Skip to content

Commit fc75728

Browse files
fix(slack): delete correct notification row instead of the last one
Notification rows were keyed by array index in NotificationsPanel, so deleting a middle row caused React to reconcile the wrong DOM node (always the last row) instead of the one that was clicked, even though the underlying store removed the correct item. Give each notification a stable id and key on that instead.
1 parent 7a7917e commit fc75728

2 files changed

Lines changed: 17 additions & 5 deletions

File tree

apps/slack/frontend/src/components/NotificationsPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const NotificationsPanel = (props: Props) => {
111111
<ChannelNote />
112112
{notifications.map((notification, index) => (
113113
<NotificationItem
114-
key={index}
114+
key={notification.id}
115115
index={index}
116116
contentTypes={contentTypes}
117117
notification={notification}

apps/slack/frontend/src/notification.store.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import create from 'zustand';
2+
import { v4 as uuidv4 } from 'uuid';
23

34
export enum SlackAppEventKey {
45
PUBLISH = 'publish',
@@ -8,6 +9,7 @@ export enum SlackAppEventKey {
89
}
910

1011
export interface SlackNotification {
12+
id: string;
1113
selectedChannel: string | null;
1214
selectedContentType: string | null;
1315
selectedEvent: Record<SlackAppEventKey, boolean>;
@@ -20,13 +22,13 @@ interface NotificationStore {
2022
setSelectedChannel: (channelId: string, index: number) => void;
2123
setSelectedContentType: (contentTypeId: string, index: number) => void;
2224
toggleEvent: (event: SlackAppEventKey, index: number) => void;
23-
createNotification: (notification?: SlackNotification) => void;
25+
createNotification: (notification?: Omit<SlackNotification, 'id'>) => void;
2426
setNotifications: (notifications: SlackNotification[]) => void;
2527
removeNotificationAtIndex: (index: number) => void;
2628
setActive: (active: boolean) => void;
2729
}
2830

29-
const NOTIFICATION_TEMPLATE: SlackNotification = {
31+
const NOTIFICATION_TEMPLATE: Omit<SlackNotification, 'id'> = {
3032
selectedChannel: null,
3133
selectedContentType: null,
3234
selectedEvent: {
@@ -73,8 +75,18 @@ export const useNotificationStore = create<NotificationStore>((set, get) => ({
7375
}),
7476
createNotification: (notification) =>
7577
set((state) => ({
76-
notifications: [...state.notifications, notification || NOTIFICATION_TEMPLATE],
78+
notifications: [
79+
...state.notifications,
80+
{ ...(notification || NOTIFICATION_TEMPLATE), id: uuidv4() },
81+
],
7782
})),
78-
setNotifications: (notifications: SlackNotification[]) => set({ notifications }),
83+
setNotifications: (notifications: SlackNotification[]) =>
84+
set({
85+
// backfill ids for notifications persisted before ids were introduced
86+
notifications: notifications.map((notification) => ({
87+
...notification,
88+
id: notification.id || uuidv4(),
89+
})),
90+
}),
7991
setActive: (active: boolean) => set({ active }),
8092
}));

0 commit comments

Comments
 (0)