Skip to content

Commit 40abbf8

Browse files
authored
Merge pull request #395 from timolins/fix-subscription-race-condition
Fix subscription race condition
2 parents 51d78b5 + e5819fb commit 40abbf8

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

.github/workflows/size.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ jobs:
77
CI_JOB_NUMBER: 1
88
steps:
99
- uses: actions/checkout@v2
10-
- uses: pnpm/action-setup@v2.2.2
10+
- uses: pnpm/action-setup@v4
1111
with:
12-
version: 7
12+
version: 9
1313
- uses: andresz1/size-limit-action@v1
1414
with:
1515
github_token: ${{ secrets.GITHUB_TOKEN }}

src/core/store.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useEffect, useState, useRef } from 'react';
22
import { DefaultToastOptions, Toast, ToastType } from './types';
33

44
const TOAST_LIMIT = 20;
@@ -143,15 +143,21 @@ export const defaultTimeouts: {
143143

144144
export const useStore = (toastOptions: DefaultToastOptions = {}): State => {
145145
const [state, setState] = useState<State>(memoryState);
146+
const initial = useRef(memoryState);
147+
148+
// TODO: Switch to useSyncExternalStore when targeting React 18+
146149
useEffect(() => {
150+
if (initial.current !== memoryState) {
151+
setState(memoryState);
152+
}
147153
listeners.push(setState);
148154
return () => {
149155
const index = listeners.indexOf(setState);
150156
if (index > -1) {
151157
listeners.splice(index, 1);
152158
}
153159
};
154-
}, [state]);
160+
}, []);
155161

156162
const mergedToasts = state.toasts.map((t) => ({
157163
...toastOptions,

test/toast.test.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import {
33
render,
44
screen,
@@ -319,3 +319,25 @@ test('pause toast', async () => {
319319

320320
expect(toastElement).not.toBeInTheDocument();
321321
});
322+
323+
test('"toast" can be called from useEffect hook', async () => {
324+
const MyComponent = () => {
325+
const [success, setSuccess] = useState(false);
326+
useEffect(() => {
327+
toast.success('Success toast');
328+
setSuccess(true);
329+
}, []);
330+
331+
return success ? <div>MyComponent finished</div> : null;
332+
};
333+
334+
render(
335+
<>
336+
<MyComponent />
337+
<Toaster />
338+
</>
339+
);
340+
341+
await screen.findByText(/MyComponent finished/i);
342+
expect(screen.queryByText(/Success toast/i)).toBeInTheDocument();
343+
});

0 commit comments

Comments
 (0)