Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: toast not appearing when toast.* called from useEffect hook #251

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Commits on Dec 13, 2022

  1. fix: toast not appearing when toast.* called from useEffect hook

    ## Issue
    After calling a toast.* function from within a useEffect hook, the toast
    does not appear (see the new test case in toast.test.tsx for an
    example).
    
    ## Cause
    The `useStore` hook (used by `Toaster`) calls "useState" to get the
    current state of the global `memoryState`, and then calls "useEffect" to
    set up a subscription to the global `memoryState`.
    
    The bug is caused when a change to the global `memoryState` happens
    after "useState" is called, but before the "useEffect" callback is run.
    This can happen e.g. if we call a toast.* function from within another
    component's useEffect hook.
    
    ## Solution
    To setup the global `memoryState` subscription, we use the
    "useLayoutEffect" hook instead. This hook runs the effect synchronously,
    so no change to the global `memoryState` can happen before the effect is
    run.
    
    ## Alternatives
    `useSyncExternalStore` is a new hook that is designed to solve this
    problem and is built into React; we could use this hook instead:
    https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore
    jluxenberg committed Dec 13, 2022
    Configuration menu
    Copy the full SHA
    464a3e8 View commit details
    Browse the repository at this point in the history

Commits on Dec 14, 2022

  1. fix: useSyncExternalStore instead of useState / useEffect

    -- Issue
    Calling a toast.* function before rendering the `<Toaster>` component,
    then rendering the `<Toaster>` component, would cause the toast to not
    appear or to appear "stacked up" on top of each other.
    
    -- Cause
    The `useStore` hook was using `useState` and `useEffect` to subscribe
    to the global `memoryState`; unfortunately, in various cases it was
    possible for change to occur to `memoryState` before the `useEffect`
    callback was called. Since the `useEffect` callback hadn't run, those
    changes didn't cause a re-render of the `<Toaster>` component.
    
    -- Solution
    Use the `useSyncExternalStore` hook instead of `useState` and
    `useEffect`; it handles these cases correctly.
    
    I've added a dependency on the `use-sync-external-store` shim so that
    React version below 18 are still supported.
    
    -- Related
    timolins#253
    jluxenberg committed Dec 14, 2022
    Configuration menu
    Copy the full SHA
    e8b5da5 View commit details
    Browse the repository at this point in the history
  2. fix: remove unused imports

    jluxenberg committed Dec 14, 2022
    Configuration menu
    Copy the full SHA
    9f1ff7c View commit details
    Browse the repository at this point in the history

Commits on May 4, 2023

  1. Merge remote-tracking branch 'origin/main' into jluxenberg/fix-issue-…

    …causing-toast-to-not-appear
    jluxenberg committed May 4, 2023
    Configuration menu
    Copy the full SHA
    09e2393 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    74f6b69 View commit details
    Browse the repository at this point in the history