diff options
author | 2022-03-31 09:51:29 -0700 | |
---|---|---|
committer | 2022-03-31 12:51:29 -0400 | |
commit | 57f48b27019bbad5c8d61808291dc8bc6cdedb52 (patch) | |
tree | 99c57190e625bdca4c03d86d14795a3a47fd98c3 /packages/integrations/react/server-v17.js | |
parent | 25c1abff10a9b46468b750ab967e9b8be44ac38a (diff) | |
download | astro-57f48b27019bbad5c8d61808291dc8bc6cdedb52.tar.gz astro-57f48b27019bbad5c8d61808291dc8bc6cdedb52.tar.zst astro-57f48b27019bbad5c8d61808291dc8bc6cdedb52.zip |
Add support for React 18 in @astrojs/react (#2947)
* First pass at supporting React 18 in @astrojs/react
* Try marking React 18’s `react-dom/client` as external
* Try a different approach to importing different React versions
* Allow resolving JSON modules
* Revert "Allow resolving JSON modules"
This reverts commit 5279b7249c52b20fd74fe48f9f1047c9b3a117dc.
* Try the separate client entrypoint approach from #2946
* Clean up diff
* Trying to see something
* Just keep swimming… 🐠
* update to support react 18
* add changeset
* add docs
Co-authored-by: delucis <swithinbank@gmail.com>
Diffstat (limited to 'packages/integrations/react/server-v17.js')
-rw-r--r-- | packages/integrations/react/server-v17.js | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/packages/integrations/react/server-v17.js b/packages/integrations/react/server-v17.js new file mode 100644 index 000000000..1c0c41286 --- /dev/null +++ b/packages/integrations/react/server-v17.js @@ -0,0 +1,67 @@ +import React from 'react'; +import ReactDOM from 'react-dom/server.js'; +import StaticHtml from './static-html.js'; + +const reactTypeof = Symbol.for('react.element'); + +function errorIsComingFromPreactComponent(err) { + return err.message && (err.message.startsWith("Cannot read property '__H'") || err.message.includes("(reading '__H')")); +} + +function check(Component, props, children) { + // Note: there are packages that do some unholy things to create "components". + // Checking the $$typeof property catches most of these patterns. + if (typeof Component === 'object') { + const $$typeof = Component['$$typeof']; + return $$typeof && $$typeof.toString().slice('Symbol('.length).startsWith('react'); + } + if (typeof Component !== 'function') return false; + + if (Component.prototype != null && typeof Component.prototype.render === 'function') { + return React.Component.isPrototypeOf(Component) || React.PureComponent.isPrototypeOf(Component); + } + + let error = null; + let isReactComponent = false; + function Tester(...args) { + try { + const vnode = Component(...args); + if (vnode && vnode['$$typeof'] === reactTypeof) { + isReactComponent = true; + } + } catch (err) { + if (!errorIsComingFromPreactComponent(err)) { + error = err; + } + } + + return React.createElement('div'); + } + + renderToStaticMarkup(Tester, props, children, {}); + + if (error) { + throw error; + } + return isReactComponent; +} + +function renderToStaticMarkup(Component, props, children, metadata) { + delete props['class']; + const vnode = React.createElement(Component, { + ...props, + children: children != null ? React.createElement(StaticHtml, { value: children }) : undefined, + }); + let html; + if (metadata && metadata.hydrate) { + html = ReactDOM.renderToString(vnode); + } else { + html = ReactDOM.renderToStaticMarkup(vnode); + } + return { html }; +} + +export default { + check, + renderToStaticMarkup, +}; |