Skip to content

Commit 33116f9

Browse files
authored
fix(toast): add ability to add multiple toasts in a single call to address #3698 (#3749)
* fix(toast): add ability to add multiple toasts in a single call to address #3698 * chore: typedocs and changeset * chore: remove array option * chore: typedocs
1 parent 820074b commit 33116f9

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed

.changeset/eighty-snails-watch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@twilio-paste/toast": minor
3+
"@twilio-paste/core": minor
4+
---
5+
6+
[Toast]: adds ability to display multiple toasts from a single call

packages/paste-core/components/toast/__tests__/useToaster.spec.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,25 @@ describe("useToaster", () => {
2727
expect(result.current.toasts.length).toEqual(1);
2828
});
2929

30+
it("should push multiple toasts by calling it twice", () => {
31+
const { result } = renderHook(() => useToaster());
32+
expect(result.current.toasts).toEqual([]);
33+
34+
act(() => {
35+
result.current.push({
36+
message: "hi",
37+
variant: "error",
38+
});
39+
// eslint-disable-next-line unicorn/no-array-push-push
40+
result.current.push({
41+
message: "hi",
42+
variant: "error",
43+
});
44+
});
45+
46+
expect(result.current.toasts.length).toEqual(2);
47+
});
48+
3049
it("should generate an id when none is passed", () => {
3150
const { result } = renderHook(() => useToaster());
3251

packages/paste-core/components/toast/src/useToaster.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const useToaster = (): UseToasterReturnedProps => {
2020
}
2121
});
2222
};
23-
}, []);
23+
}, [toasts]);
2424

2525
const pop = (id: ToasterToast["id"]): void => {
2626
if (!isMounted.current) {
@@ -50,26 +50,29 @@ export const useToaster = (): UseToasterReturnedProps => {
5050
}
5151

5252
const generatedID = uid(newToast);
53-
let timeOutId;
53+
let timeOutId: number;
5454
/*
5555
* if you are setting a dismissAfter time, we need to grab a timeout id to use later if we need to clear the timeout
5656
* for that particular toast. We also need to make sure the time is an integer to prevent locking the browser
5757
*/
5858
if (newToast.dismissAfter != null && Number.isInteger(newToast.dismissAfter)) {
5959
timeOutId = window.setTimeout(pop, newToast.dismissAfter, newToast.id || generatedID);
6060
}
61-
/*
62-
* We set a new toast to always setFocus. For all the existing toasts in the stack, we need to clear setFocus
63-
* without creating a new state object. If you create a new state object, you cause react spring to rerun
64-
* all the animations for the entire stack. So we mutate existing state instead.
65-
*/
66-
const existingToasts = toasts.map((toast) => {
67-
const tmpToast = toast;
68-
tmpToast.setFocus = false;
69-
return tmpToast;
70-
});
61+
7162
// add the new toast with a generatedID, timeoutid and setFocus to true. Allow for user to override
72-
setToasts([{ id: generatedID, timeOutId, setFocus: true, ...newToast }, ...existingToasts]);
63+
setToasts((state) => {
64+
/*
65+
* We set a new toast to always setFocus. For all the existing toasts in the stack, we need to clear setFocus
66+
* without creating a new state object. If you create a new state object, you cause react spring to rerun
67+
* all the animations for the entire stack. So we mutate existing state instead.
68+
*/
69+
const existingToasts = state.map((toast) => {
70+
const tmpToast = toast;
71+
tmpToast.setFocus = false;
72+
return tmpToast;
73+
});
74+
return [{ id: generatedID, timeOutId, setFocus: true, ...newToast }, ...existingToasts];
75+
});
7376
};
7477

7578
return { toasts, push, pop };

0 commit comments

Comments
 (0)