Skip to content

feat(v6): add support for deterministic loading#849

Merged
gregjopa merged 7 commits intomainfrom
support-script-reloading
Mar 2, 2026
Merged

feat(v6): add support for deterministic loading#849
gregjopa merged 7 commits intomainfrom
support-script-reloading

Conversation

@gregjopa
Copy link
Contributor

@gregjopa gregjopa commented Mar 2, 2026

This PR adds a data-loading-state attribute to the V6 Core SDK script tag. This is leveraged to ensure that the v6 script only loads once, regardless of how many times the loadCoreSdkScript() function is called. This will help resolved any issue around useEffect running twice in react in strict mode.

@changeset-bot
Copy link

changeset-bot bot commented Mar 2, 2026

🦋 Changeset detected

Latest commit: af06719

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@paypal/paypal-js Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gregjopa gregjopa marked this pull request as ready for review March 2, 2026 17:59
@gregjopa gregjopa requested a review from a team as a code owner March 2, 2026 17:59
SCRIPT_LOADING_STATE.RESOLVED,
);
return resolve(paypalWindowReference);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
});
}, { once: true });

to remove listener when triggered

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion @HackTheW2d! I added this once option to both listeners

SCRIPT_LOADING_STATE.REJECTED,
);
return reject(defaultError);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
});
}, { once: true });

same here

Copy link
Contributor

@EvanReinstein EvanReinstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great @gregjopa Thanks for taking this up. I tested in the React sample integration and am only seeing 1 core script element and no console errors related to registering components more than once 👍

expect(window.paypal).toBeDefined();
});

test("should avoid inserting two script elements when called twice", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently we await the first load to be fully resolved then trigger the second one.

Do we want to add one more test to test concurrency like this? :) Thanks!

  test("should handle concurrent calls without duplicating script elements",    
  async () => {   
      // no await here!                         
      const promise1 = loadCoreSdkScript();
      const promise2 = loadCoreSdkScript();

      const [result1, result2] = await Promise.all([promise1, promise2]);

      // and we only expect one insert
      expect(scriptAppendChildSpy).toHaveBeenCalledTimes(1);

      // both get resolved correctly without hanging
      expect(result1).toBeDefined();
      expect(result2).toBeDefined();

      // they get same ref
      expect(result1).toBe(result2);

      // scriptElement to be resolved
      const scriptElement = scriptAppendChildSpy.mock.calls[0][0];
      expect(scriptElement.getAttribute("data-loading-state")).toBe("resolved");
  });

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dig it! I added this parallel test 💯

Copy link
Contributor

@HackTheW2d HackTheW2d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Nice work! some non-blocking comments

@gregjopa gregjopa merged commit 8663d7f into main Mar 2, 2026
5 checks passed
@gregjopa gregjopa deleted the support-script-reloading branch March 2, 2026 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants