From 2740d17e1dd2d2e109f466a49431adef91845d72 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Tue, 19 Jul 2022 16:48:40 +1000 Subject: [PATCH 1/3] Reinstate all react tests --- code/cypress/generated/addon-docs.spec.ts | 34 ++++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/code/cypress/generated/addon-docs.spec.ts b/code/cypress/generated/addon-docs.spec.ts index e09c7797cca0..2c53141f7cf0 100644 --- a/code/cypress/generated/addon-docs.spec.ts +++ b/code/cypress/generated/addon-docs.spec.ts @@ -8,28 +8,22 @@ describe('addon-docs', () => { skipOn('vue3', () => { skipOn('html', () => { - skipOn('react', () => { - skipOn('cra', () => { - skipOn('react_legacy_root_api', () => { - it('should provide source snippet', () => { - cy.getDocsElement() - .find('.docblock-code-toggle') - .each(($div) => { - cy.wrap($div) - .should('contain.text', 'Show code') - // use force click so cypress does not automatically scroll, making the source block visible on this step - .click({ force: true }); - }); + it('should provide source snippet', () => { + cy.getDocsElement() + .find('.docblock-code-toggle') + .each(($div) => { + cy.wrap($div) + .should('contain.text', 'Show code') + // use force click so cypress does not automatically scroll, making the source block visible on this step + .click({ force: true }); + }); - cy.getDocsElement() - .find('pre.prismjs') - .each(($div) => { - const text = $div.text(); - expect(text).not.match(/^\(args\) => /); - }); - }); + cy.getDocsElement() + .find('pre.prismjs') + .each(($div) => { + const text = $div.text(); + expect(text).not.match(/^\(args\) => /); }); - }); }); }); }); From 049d84c44fe3768d10e798e65972e6b2aab47724 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Tue, 19 Jul 2022 16:49:01 +1000 Subject: [PATCH 2/3] Use `useLayoutEffect` for callback --- code/renderers/react/src/render.tsx | 30 ++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/code/renderers/react/src/render.tsx b/code/renderers/react/src/render.tsx index 2bcad1628cc5..bf81b32b0dbd 100644 --- a/code/renderers/react/src/render.tsx +++ b/code/renderers/react/src/render.tsx @@ -1,7 +1,15 @@ // @ts-ignore import global from 'global'; -import React, { Component as ReactComponent, FC, ReactElement, StrictMode, Fragment } from 'react'; +import React, { + Component as ReactComponent, + FC, + ReactElement, + StrictMode, + Fragment, + useLayoutEffect, + useRef, +} from 'react'; import ReactDOM, { version as reactDomVersion } from 'react-dom'; import type { Root as ReactRoot } from 'react-dom/client'; @@ -26,16 +34,28 @@ export const render: ArgsStoryFn = (args, context) => { return ; }; +const WithCallback: FC<{ callback: () => void; children: ReactElement }> = ({ + callback, + children, +}) => { + // See https://github.com/reactwg/react-18/discussions/5#discussioncomment-2276079 + const once = useRef(false); + useLayoutEffect(() => { + if (once.current) return; + once.current = true; + callback(); + }, [callback]); + + return children; +}; + const renderElement = async (node: ReactElement, el: Element) => { // Create Root Element conditionally for new React 18 Root Api const root = await getReactRoot(el); return new Promise((resolve) => { if (root) { - root.render(node); - setTimeout(() => { - resolve(null); - }, 0); + root.render( resolve(null)}>{node}); } else { ReactDOM.render(node, el, () => resolve(null)); } From b2b7a155170475c081dfa9f723b75fd7606634c5 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 20 Jul 2022 12:12:18 +1000 Subject: [PATCH 3/3] Add a `Math.random()` to ensure the callback is called exactly once --- code/renderers/react/src/render.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/renderers/react/src/render.tsx b/code/renderers/react/src/render.tsx index bf81b32b0dbd..df56d64da981 100644 --- a/code/renderers/react/src/render.tsx +++ b/code/renderers/react/src/render.tsx @@ -55,7 +55,11 @@ const renderElement = async (node: ReactElement, el: Element) => { return new Promise((resolve) => { if (root) { - root.render( resolve(null)}>{node}); + root.render( + resolve(null)}> + {node} + + ); } else { ReactDOM.render(node, el, () => resolve(null)); }