diff --git a/.changeset/tame-seas-sort.md b/.changeset/tame-seas-sort.md new file mode 100644 index 000000000000..fdfed90bee26 --- /dev/null +++ b/.changeset/tame-seas-sort.md @@ -0,0 +1,9 @@ +--- +'astro': patch +--- + +Prevent React hook call warnings when used with MDX + +When React and MDX are used in the same project, if the MDX integration is added before React, previously you'd get a warning about hook calls. + +This makes it so that the MDX integration's JSX renderer is last in order. diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts index 9b7770c1cef6..7cf1387c7a41 100644 --- a/packages/astro/src/integrations/index.ts +++ b/packages/astro/src/integrations/index.ts @@ -73,6 +73,7 @@ export async function runHookConfigSetup({ let updatedConfig: AstroConfig = { ...settings.config }; let updatedSettings: AstroSettings = { ...settings, config: updatedConfig }; let addedClientDirectives = new Map>(); + let astroJSXRenderer: AstroRenderer | null = null; for (const integration of settings.config.integrations) { /** @@ -103,7 +104,11 @@ export async function runHookConfigSetup({ throw new Error(`Renderer ${bold(renderer.name)} does not provide a serverEntrypoint.`); } - updatedSettings.renderers.push(renderer); + if(renderer.name === 'astro:jsx') { + astroJSXRenderer = renderer; + } else { + updatedSettings.renderers.push(renderer); + } }, injectScript: (stage, content) => { updatedSettings.scripts.push({ stage, content }); @@ -174,6 +179,11 @@ export async function runHookConfigSetup({ } } + // The astro:jsx renderer should come last, to not interfere with others. + if(astroJSXRenderer) { + updatedSettings.renderers.push(astroJSXRenderer); + } + updatedSettings.config = updatedConfig; return updatedSettings; } diff --git a/packages/integrations/mdx/test/fixtures/mdx-plus-react/astro.config.mjs b/packages/integrations/mdx/test/fixtures/mdx-plus-react/astro.config.mjs index 4671227d3ea1..fd017ed8ebea 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-plus-react/astro.config.mjs +++ b/packages/integrations/mdx/test/fixtures/mdx-plus-react/astro.config.mjs @@ -2,5 +2,5 @@ import mdx from '@astrojs/mdx'; import react from '@astrojs/react'; export default { - integrations: [react(), mdx()] + integrations: [mdx(), react()] } diff --git a/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/components/Component.jsx b/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/components/Component.jsx index 53f5dad3f108..70c3363148b7 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/components/Component.jsx +++ b/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/components/Component.jsx @@ -1,5 +1,8 @@ +import { useState } from "react"; + const Component = () => { - return

Hello world

; + const [name] = useState('world'); + return

Hello {name}

; }; export default Component; diff --git a/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/pages/post.mdx b/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/pages/post.mdx new file mode 100644 index 000000000000..734f33e82486 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-plus-react/src/pages/post.mdx @@ -0,0 +1,3 @@ +# Testing + +This works! diff --git a/packages/integrations/mdx/test/mdx-plus-react.test.js b/packages/integrations/mdx/test/mdx-plus-react.test.js index 22d7ca0e721b..904c58b141d7 100644 --- a/packages/integrations/mdx/test/mdx-plus-react.test.js +++ b/packages/integrations/mdx/test/mdx-plus-react.test.js @@ -2,13 +2,27 @@ import { expect } from 'chai'; import { parseHTML } from 'linkedom'; import { loadFixture } from '../../../astro/test/test-utils.js'; +function hookError() { + const error = console.error; + const errors = []; + console.error = function(...args) { + errors.push(args); + }; + return () => { + console.error = error; + return errors; + }; +} + describe('MDX and React', () => { let fixture; + let unhook; before(async () => { fixture = await loadFixture({ root: new URL('./fixtures/mdx-plus-react/', import.meta.url), }); + unhook = hookError(); await fixture.build(); }); @@ -20,4 +34,16 @@ describe('MDX and React', () => { expect(p.textContent).to.equal('Hello world'); }); + + it('mdx renders fine', async () => { + const html = await fixture.readFile('/post/index.html'); + const { document } = parseHTML(html); + const h = document.querySelector('#testing'); + expect(h.textContent).to.equal('Testing'); + }); + + it('does not get a invalid hook call warning', () => { + const errors = unhook(); + expect(errors).to.have.a.lengthOf(0); + }); });