File tree Expand file tree Collapse file tree 4 files changed +79
-0
lines changed
assets/js/phoenix_live_view Expand file tree Collapse file tree 4 files changed +79
-0
lines changed Original file line number Diff line number Diff line change @@ -754,6 +754,12 @@ export default class View {
754754 }
755755
756756 applyPendingUpdates ( ) {
757+ // prevent race conditions where we might still be pending a new
758+ // navigation after applying the current one;
759+ // if we call update and a pendingDiff is not applied, it would
760+ // be silently dropped otherwise, as update would push it back to
761+ // pendingDiffs, but we clear it immediately after
762+ if ( this . liveSocket . hasPendingLink ( ) && this . root . isMain ( ) ) { return }
757763 this . pendingDiffs . forEach ( ( { diff, events} ) => this . update ( diff , events ) )
758764 this . pendingDiffs = [ ]
759765 this . eachChild ( child => child . applyPendingUpdates ( ) )
Original file line number Diff line number Diff line change 1+ defmodule Phoenix.LiveViewTest.E2E.Issue3709Live do
2+ # https://github.com/phoenixframework/phoenix_live_view/issues/3709
3+ use Phoenix.LiveView
4+
5+ defmodule SomeComponent do
6+ use Phoenix.LiveComponent
7+
8+ def render ( assigns ) do
9+ ~H"""
10+ < div >
11+ Hello
12+ </ div >
13+ """
14+ end
15+ end
16+
17+ def mount ( _params , _session , socket ) do
18+ { :ok , assign ( socket , id: nil ) }
19+ end
20+
21+ def handle_params ( params , _ , socket ) do
22+ { :noreply , assign ( socket , :id , params [ "id" ] ) }
23+ end
24+
25+ def render ( assigns ) do
26+ ~H"""
27+ < ul >
28+ < li :for = { i <- 1 .. 10 } >
29+ < . link patch = { "/issues/3709/#{ i } " } > Link { i } </ . link >
30+ </ li >
31+ </ ul >
32+ < div >
33+ < . live_component module = { SomeComponent } id = { "user-#{ @ id } " } /> id: { @ id }
34+ < div >
35+ Click the button, then click any link.
36+ < button onclick = "document.querySelectorAll('li a').forEach((x) => x.click()) " >
37+ Break Stuff
38+ </ button >
39+ </ div >
40+ </ div >
41+ """
42+ end
43+ end
Original file line number Diff line number Diff line change @@ -163,6 +163,8 @@ defmodule Phoenix.LiveViewTest.E2E.Router do
163163 live "/3656" , Issue3656Live
164164 live "/3658" , Issue3658Live
165165 live "/3684" , Issue3684Live
166+ live "/3709" , Issue3709Live
167+ live "/3709/:id" , Issue3709Live
166168 end
167169 end
168170
Original file line number Diff line number Diff line change 1+ const { test, expect} = require ( "../../test-fixtures" )
2+ const { syncLV} = require ( "../../utils" )
3+
4+ // https://github.com/phoenixframework/phoenix_live_view/issues/3709
5+ test ( "pendingDiffs don't race with navigation" , async ( { page} ) => {
6+ const logs = [ ]
7+ page . on ( "console" , ( e ) => logs . push ( e . text ( ) ) )
8+ const errors = [ ]
9+ page . on ( "pageerror" , ( err ) => errors . push ( err ) )
10+
11+ await page . goto ( "/issues/3709/1" )
12+ await syncLV ( page )
13+ await expect ( page . locator ( "body" ) ) . toContainText ( "id: 1" )
14+
15+ await page . getByRole ( "button" , { name : "Break Stuff" } ) . click ( )
16+ await syncLV ( page )
17+
18+ expect ( logs ) . not . toEqual ( expect . arrayContaining ( [ expect . stringMatching ( "Cannot read properties of undefined (reading 's')" ) ] ) )
19+
20+ await page . getByRole ( "link" , { name : "Link 5" } ) . click ( )
21+ await syncLV ( page )
22+ await expect ( page . locator ( "body" ) ) . toContainText ( "id: 5" )
23+
24+ expect ( logs ) . not . toEqual ( expect . arrayContaining ( [ expect . stringMatching ( "Cannot set properties of undefined (setting 'newRender')" ) ] ) )
25+
26+ // no uncaught exceptions
27+ expect ( errors ) . toEqual ( [ ] )
28+ } )
You can’t perform that action at this time.
0 commit comments