From fc9a625414bd2dad084936e33926f7e86f5936ac Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 16 Mar 2023 16:30:58 +0100 Subject: [PATCH] Fix "Can't perform a React state update on an unmounted component." when using the `Transition` component (#2374) * only change flags when mounted * update changelog --- packages/@headlessui-react/CHANGELOG.md | 1 + .../@headlessui-react/src/hooks/use-flags.ts | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index 893c5e8b04..15172d2a54 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix focus styles showing up when using the mouse ([#2347](https://github.com/tailwindlabs/headlessui/pull/2347)) +- Fix "Can't perform a React state update on an unmounted component." when using the `Transition` component ([#2374](https://github.com/tailwindlabs/headlessui/pull/2374)) ### Added diff --git a/packages/@headlessui-react/src/hooks/use-flags.ts b/packages/@headlessui-react/src/hooks/use-flags.ts index e8a8cfef8e..5d0bfb367e 100644 --- a/packages/@headlessui-react/src/hooks/use-flags.ts +++ b/packages/@headlessui-react/src/hooks/use-flags.ts @@ -1,12 +1,32 @@ import { useState, useCallback } from 'react' +import { useIsMounted } from './use-is-mounted' export function useFlags(initialFlags = 0) { let [flags, setFlags] = useState(initialFlags) + let mounted = useIsMounted() - let addFlag = useCallback((flag: number) => setFlags((flags) => flags | flag), [flags]) + let addFlag = useCallback( + (flag: number) => { + if (!mounted.current) return + setFlags((flags) => flags | flag) + }, + [flags, mounted] + ) let hasFlag = useCallback((flag: number) => Boolean(flags & flag), [flags]) - let removeFlag = useCallback((flag: number) => setFlags((flags) => flags & ~flag), [setFlags]) - let toggleFlag = useCallback((flag: number) => setFlags((flags) => flags ^ flag), [setFlags]) + let removeFlag = useCallback( + (flag: number) => { + if (!mounted.current) return + setFlags((flags) => flags & ~flag) + }, + [setFlags, mounted] + ) + let toggleFlag = useCallback( + (flag: number) => { + if (!mounted.current) return + setFlags((flags) => flags ^ flag) + }, + [setFlags] + ) return { flags, addFlag, hasFlag, removeFlag, toggleFlag } }