UIPageLayout PageEnter event fails to fire when Next() and Previous() are called in rapid succession

I’ve found an issue where UIPageLayout’s PageEnter event does not always fire when navigation methods are triggered quickly in opposite directions.

This happens when Next() is called and, almost immediately afterward, Previous() is called (for example, due to a fast double-click or overlapping UI interactions). The UIPageLayout does visually change pages correctly, but the PageEnter signal fails to fire for the final page.


Expected Behavior

Each time the displayed page changes — regardless of how quickly or in which direction — the PageEnter event should fire for the newly active page.


Actual Behavior

When Next() is immediately followed by Previous() (or vice-versa):

  • The page changes correctly on-screen
  • But PageEnter never fires for the second transition
  • Only the first PageEnter event fires

This causes logic tied to PageEnter (e.g., setup, validation, animations, UI state updates) to fail.


Simplified Reproduction Steps

  1. Create a UIPageLayout with three pages.

  2. Connect to its PageEnter event:

    PageLayout.PageEnter:Connect(function(page)
        print("Entered:", page.Name)
    end)
    
  3. In a LocalScript, add:

    PageLayout:Next()
    PageLayout:Previous()
    
  4. Run the script with both calls executed in the same frame or very close together.

  5. Observe:

    • The page visually returns to the original page
    • Only one PageEnter fires, not two

Reproducibility

  • Occurs consistently in Studio and live client
  • Happens across multiple devices
  • Not dependent on specific UI or button placement

Impact

This breaks UI flows relying on PageEnter for:

  • Page initialization
  • Validation
  • Animated transitions
  • State resets
  • Dynamic UI loading

Here are test results that I’ve conducted.

The PageLayout has a TweenTime of 0.25, and there is a 0.1 second delay between switching pages.

Here is the code I used for this test:

local gui = script.Parent
local pageLayout = gui:FindFirstChildWhichIsA("UIPageLayout")
local lastEntered

if not pageLayout then
	warn("No UIPageLayout found in parent!")
	return
end

-- Wait so you can see the starting page
task.wait(1)
warn("PAGELAYOUT TEST: Starting test...")
warn("Inital page name:", pageLayout.CurrentPage.Name)

-- Print when entering a page
pageLayout.PageEnter:Connect(function(page)
	warn("PageEnter fired for:", page.Name)
	lastEntered = page
end)

-- Trigger the bug: call Next() then Previous() immediately
pageLayout:Next()
task.wait(0.1)
pageLayout:Previous()

warn("PAGELAYOUT TEST: Test executed: Expected 2 PageEnter events")
warn("CURRENT PAGE:", pageLayout.CurrentPage.Name)
warn("LAST ENTERED:", lastEntered.Name)

Hi Vinny, it is expected behavior for PageEnter to fire only when the page has come back into view and is about to be rendered per the official documentation.

PageEnter

Fires when a page comes into view, and is going to be rendered.

In your example, since the pages are being swapped so rapidly, the original page never goes out of view. Consequently, when returning to that page, it will not come back into view because it has always been in view.

I understand it may be confusing to tie these signals to rendering. I would recommend instead connecting a property changed signal to CurrentPage if you are simply trying run logic when Previous(), Next(), and JumpTo() update the current page. Let me know if this workaround works for you!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.