Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error using Fragment shorthand in React Typescript project #564

Closed
breadadams opened this issue Feb 14, 2020 · 3 comments · Fixed by #573
Closed

Error using Fragment shorthand in React Typescript project #564

breadadams opened this issue Feb 14, 2020 · 3 comments · Fixed by #573
Labels
has-fix A fix is available, but may not yet be released.

Comments

@breadadams
Copy link

breadadams commented Feb 14, 2020

After recently migrating a project over from Flow to TypeScript I've noticed a difference when using the Fragment shorthand (<></>). We have the following utility:

export const FragmentPassThrough: React.FC<{ children: React.ReactNode }> = ({
  children
}) => <>{children}</>;

With Flow, it compiled as follows:

ro = function(e) {
  return t.createElement(n.Fragment, null, e.children);
};

After moving to TS though, it doesn't take Fragment from React (eg. n):

Kr = function Kr(e) {
  return t.createElement(Fragment, null, e.children);
}

Resulting in the following error when using the bundle:

image

Full stack trace
index.js:formatted:1 Uncaught ReferenceError: Fragment is not defined
    at Kr (index.js:formatted:1)
    at renderWithHooks (index.js:formatted:1)
    at mountIndeterminateComponent (index.js:formatted:1)
    at beginWork (index.js:formatted:1)
    at performUnitOfWork (index.js:formatted:1)
    at workLoop (index.js:formatted:1)
    at HTMLUnknownElement.callCallback (index.js:formatted:1)
    at Object.invokeGuardedCallbackDev (index.js:formatted:1)
    at invokeGuardedCallback (index.js:formatted:1)
    at replayUnitOfWork (index.js:formatted:1)
    at renderRoot (index.js:formatted:1)
    at performWorkOnRoot (index.js:formatted:1)
    at performWork (index.js:formatted:1)
    at performSyncWork (index.js:formatted:1)
    at interactiveUpdates$1 (index.js:formatted:1)
    at interactiveUpdates (index.js:formatted:1)
    at dispatchInteractiveEvent (index.js:formatted:1)
Kr @ index.js:formatted:1
renderWithHooks @ index.js:formatted:1
mountIndeterminateComponent @ index.js:formatted:1
beginWork @ index.js:formatted:1
performUnitOfWork @ index.js:formatted:1
workLoop @ index.js:formatted:1
callCallback @ index.js:formatted:1
invokeGuardedCallbackDev @ index.js:formatted:1
invokeGuardedCallback @ index.js:formatted:1
replayUnitOfWork @ index.js:formatted:1
renderRoot @ index.js:formatted:1
performWorkOnRoot @ index.js:formatted:1
performWork @ index.js:formatted:1
performSyncWork @ index.js:formatted:1
interactiveUpdates$1 @ index.js:formatted:1
interactiveUpdates @ index.js:formatted:1
dispatchInteractiveEvent @ index.js:formatted:1
index.js:formatted:1 The above error occurred in the  component:
    in Kr (created by r)
    in div (created by Context.Consumer)
    in EmotionCssPropInternal (created by SelectContainer)
    in SelectContainer (created by r)
    in r (created by r)
    in r (created by Context.Consumer)
    in StyledComponent (created by Styled(r))
    in Styled(r)
    in Unknown (at createForm.js:117)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at createForm.js:116)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at createForm.js:108)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at Form/index.js:91)
    in Form (at FormTable.js:291)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at FormTable.js:289)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at FormTable.js:281)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div
    in Unknown (at FormTable.js:268)
    in FormTable (at createForm.js:148)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at createForm.js:147)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at Form/index.js:91)
    in Form (at FieldGroupModal.js:24)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (created by Me)
    in div (created by ModalPortal)
    in div (created by ModalPortal)
    in ModalPortal (created by Modal)
    in Modal
    in Unknown (created by Context.Consumer)
    in StyledComponent (created by Styled(Component))
    in Styled(Component) (created by Me)
    in Me (at FieldGroupModal.js:23)
    in FieldGroupModal (at GroupsTab.js:180)
    in GroupsTab (at Edit/index.js:33)
    in div (created by TabPanel)
    in TabPanel
    in div (created by UncontrolledTabs)
    in UncontrolledTabs (created by Tabs)
    in Tabs
    in Unknown (at Edit/index.js:45)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (at Edit/index.js:44)
    in Edit (created by Context.Consumer)
    in Route (at App.js:35)
    in Switch (at App.js:32)
    in main (created by Context.Consumer)
    in StyledComponent (created by styled.main)
    in styled.main (at PageWrap.js:37)
    in PageWrap (at App.js:31)
    in App (at src/index.js:59)
    in Router (created by BrowserRouter)
    in BrowserRouter (at src/index.js:58)
    in AppContextProvider (at src/index.js:56)
    in ApolloProvider (at src/index.js:55)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
console. @ index.js:formatted:1
r @ backend.js:6
logCapturedError @ index.js:formatted:1
logError @ index.js:formatted:1
update.callback @ index.js:formatted:1
callCallback @ index.js:formatted:1
commitUpdateEffects @ index.js:formatted:1
commitUpdateQueue @ index.js:formatted:1
commitLifeCycles @ index.js:formatted:1
commitAllLifeCycles @ index.js:formatted:1
callCallback @ index.js:formatted:1
invokeGuardedCallbackDev @ index.js:formatted:1
invokeGuardedCallback @ index.js:formatted:1
commitRoot @ index.js:formatted:1
(anonymous) @ index.js:formatted:1
unstable_runWithPriority @ index.js:formatted:1
completeRoot @ index.js:formatted:1
performWorkOnRoot @ index.js:formatted:1
performWork @ index.js:formatted:1
performSyncWork @ index.js:formatted:1
interactiveUpdates$1 @ index.js:formatted:1
interactiveUpdates @ index.js:formatted:1
dispatchInteractiveEvent @ index.js:formatted:1
index.js:formatted:1 Uncaught ReferenceError: Fragment is not defined
at Kr (index.js:formatted:1)
at renderWithHooks (index.js:formatted:1)
at mountIndeterminateComponent (index.js:formatted:1)
at beginWork (index.js:formatted:1)
at performUnitOfWork (index.js:formatted:1)
at workLoop (index.js:formatted:1)
at renderRoot (index.js:formatted:1)
at performWorkOnRoot (index.js:formatted:1)
at performWork (index.js:formatted:1)
at performSyncWork (index.js:formatted:1)
at interactiveUpdates$1 (index.js:formatted:1)
at interactiveUpdates (index.js:formatted:1)
at dispatchInteractiveEvent (index.js:formatted:1)
Kr @ index.js:formatted:1
renderWithHooks @ index.js:formatted:1
mountIndeterminateComponent @ index.js:formatted:1
beginWork @ index.js:formatted:1
performUnitOfWork @ index.js:formatted:1
workLoop @ index.js:formatted:1
renderRoot @ index.js:formatted:1
performWorkOnRoot @ index.js:formatted:1
performWork @ index.js:formatted:1
performSyncWork @ index.js:formatted:1
interactiveUpdates$1 @ index.js:formatted:1
interactiveUpdates @ index.js:formatted:1
dispatchInteractiveEvent @ index.js:formatted:1


As a temporary solution we've replaced the shorthand with an imported Fragment and it now compiles as expected:

export const FragmentPassThrough: React.FC<{ children: React.ReactNode }> = ({
  children
}) => <Fragment>{children}</Fragment>;
Kr = function Kr(e) {
    return t.createElement(n.Fragment, null, e.children);
}

Versions
  • Microbundle 0.12.0-next.8
  • React 16.12.0
  • Typescript 3.7.5
Build script:

microbundle --jsx React.createElement --format cjs,umd

@developit
Copy link
Owner

@breadadams does this still break if you set the following in your tsconfig.json?

{
  "compilerOptions": {
    "jsx": "preserve"
  }
}

@breadadams
Copy link
Author

Apparently yes @developit, we already have that property set - sorry, should have shared our tsconfig:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "noEmit": true,
    "jsx": "preserve"
  },
  "include": ["src"]
}

I think it's pretty much the default from a CRA.

@developit
Copy link
Owner

developit commented Mar 1, 2020

I think we are accidentally processing JSX in TypeScript here:

microbundle/src/index.js

Lines 553 to 554 in 8cc0d7b

jsx: 'react',
jsxFactory: options.jsx || 'h',

We should probably be doing it in Babel (draft PR), since TypeScript has been dragging their heels on supporting configurable Fragment pragma for over a year.

Now, if I'm wrong about the above, you should be able to get fragment syntax working properly by setting the --jsxFragment command line flag:

microbundle --jsxFragment React.Fragment

@developit developit added the has-fix A fix is available, but may not yet be released. label Apr 5, 2020
bors bot pushed a commit that referenced this issue Jul 21, 2020
It seems like we're allowing TypeScript to transpile JSX, when we could be allowing Babel to do so. Having TypeScript pass-through JSX to babel would mean we only have to support it being configurable in one place.

(hoping this fixes #564)

Co-authored-by: Leah <me@hrmny.sh>
Co-authored-by: Leah <github.leah@hrmny.sh>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has-fix A fix is available, but may not yet be released.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants