From a1bc767a972babf67fce8035ae39a35389bf88ff Mon Sep 17 00:00:00 2001 From: Houssein Djirdeh Date: Wed, 20 Jul 2022 16:49:26 -0400 Subject: [PATCH] adds onReady prop to next/script --- docs/api-reference/next/script.md | 35 +++++++++++++++++-- docs/basic-features/script.md | 34 ++++++++++++++++-- packages/next/client/script.tsx | 22 +++++++++++- .../script-loader/base/pages/page8.js | 24 +++++++++++++ .../script-loader/base/pages/page9.js | 11 ++++++ .../script-loader/test/index.test.js | 24 +++++++++++++ 6 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 test/integration/script-loader/base/pages/page8.js create mode 100644 test/integration/script-loader/base/pages/page9.js diff --git a/docs/api-reference/next/script.md b/docs/api-reference/next/script.md index c1470361fcc1..8fe127a791bb 100644 --- a/docs/api-reference/next/script.md +++ b/docs/api-reference/next/script.md @@ -20,6 +20,7 @@ description: Optimize loading of third-party scripts with the built-in Script co | Version | Changes | | --------- | ------------------------- | +| `v12.2.3` | `onReady` prop added. | | `v11.0.0` | `next/script` introduced. | @@ -47,9 +48,9 @@ The loading strategy of the script. ### onLoad -A method that returns additional JavaScript that should be executed after the script has finished loading. +A method that returns additional JavaScript that should be executed once after the script has finished loading. -> **Note: `onLoad` can't be used with the `beforeInteractive` loading strategy.** +> **Note: `onLoad` can't be used with the `beforeInteractive` loading strategy. Consider using `onReady` instead.** The following is an example of how to use the `onLoad` property: @@ -74,6 +75,36 @@ export default function Home() { } ``` +### onReady + +A method that returns additional JavaScript that should be executed after the script has finished loading and every time the component is mounted. + +The following is an example of how to use the `onReady` property: + +```jsx +import { useState } from 'react' +import Script from 'next/script' + +export default function Home() { + const [stripe, setStripe] = useState(null) + + return ( + <> + + + ) +} + +export default Page diff --git a/test/integration/script-loader/base/pages/page9.js b/test/integration/script-loader/base/pages/page9.js new file mode 100644 index 000000000000..6e82d8627683 --- /dev/null +++ b/test/integration/script-loader/base/pages/page9.js @@ -0,0 +1,11 @@ +import Link from 'next/link' + +const Page = () => { + return ( + <> + Page 8 + + ) +} + +export default Page diff --git a/test/integration/script-loader/test/index.test.js b/test/integration/script-loader/test/index.test.js index 0a5ca5d50440..cad3fc6bede1 100644 --- a/test/integration/script-loader/test/index.test.js +++ b/test/integration/script-loader/test/index.test.js @@ -190,6 +190,30 @@ describe('Next.js Script - Primary Strategies', () => { } }) + it('onReady fires after load event and then on every subsequent re-mount', async () => { + let browser + try { + browser = await webdriver(appPort, '/page8') + + const text = await browser.elementById('text').text() + + expect(text).toBe('aaa') + + // Navigate to different page and back + await browser.waitForElementByCss('[href="/page9"]') + await browser.click('[href="/page9"]') + await browser.waitForElementByCss('[href="/page8"]') + await browser.click('[href="/page8"]') + + await browser.waitForElementByCss('.container') + const sameText = await browser.elementById('text').text() + + expect(sameText).toBe('aaa') // onReady should fire again + } finally { + if (browser) await browser.close() + } + }) + it('priority beforeInteractive with inline script', async () => { const html = await renderViaHTTP(appPort, '/page5') const $ = cheerio.load(html)