diff --git a/package.json b/package.json index 9c93dd7..a7746df 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "goober": "^2.1.16" }, "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" + "react": ">=18", + "react-dom": ">=18" } } diff --git a/src/core/store.ts b/src/core/store.ts index 4909dcf..52be25b 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useSyncExternalStore } from 'react'; import { DefaultToastOptions, Toast, ToastType } from './types'; const TOAST_LIMIT = 20; @@ -142,16 +142,19 @@ export const defaultTimeouts: { }; export const useStore = (toastOptions: DefaultToastOptions = {}): State => { - const [state, setState] = useState(memoryState); - useEffect(() => { - listeners.push(setState); - return () => { - const index = listeners.indexOf(setState); - if (index > -1) { - listeners.splice(index, 1); - } - }; - }, [state]); + const state = useSyncExternalStore( + (callback) => { + listeners.push(callback); + return () => { + const index = listeners.indexOf(callback); + if (index > -1) { + listeners.splice(index, 1); + } + }; + }, + () => memoryState, + () => memoryState + ); const mergedToasts = state.toasts.map((t) => ({ ...toastOptions, diff --git a/test/toast.test.tsx b/test/toast.test.tsx index c528219..a79d689 100644 --- a/test/toast.test.tsx +++ b/test/toast.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { render, screen, @@ -319,3 +319,25 @@ test('pause toast', async () => { expect(toastElement).not.toBeInTheDocument(); }); + +test('"toast" can be called from useEffect hook', async () => { + const MyComponent = () => { + const [success, setSuccess] = useState(false); + useEffect(() => { + toast.success('Success toast'); + setSuccess(true); + }, []); + + return success ?
MyComponent finished
: null; + }; + + render( + <> + + + + ); + + await screen.findByText(/MyComponent finished/i); + expect(screen.queryByText(/Success toast/i)).toBeInTheDocument(); +});