Js-lingui: React.cloneElement undefined argument error when translation contains HTML markup

Created on 2 Aug 2018  ·  3Comments  ·  Source: lingui/js-lingui

Describe the bug
React shows the following error message when a <Trans> element contains text with HTML markup and has an id attribute assigned. If the id is omitted the <Trans> block appears blank instead of causing an error message.

Error Message

React.cloneElement(...): The argument must be a React element, but you passed undefined.
▶ 29 stack frames were collapsed.
./src/index.js
src/index.js:16
  13 |     }
  14 | });
  15 | 
> 16 | ReactDOM.render(
  17 |     <I18nProvider language="en" catalogs={{ en: catalog }}>
  18 |         <SignIn/>
  19 |     </I18nProvider>,
View compiled
▶ 6 stack frames were collapsed.

Collapsed Stackframes

node_modules/fbjs/lib/invariant.js:42
cloneElement
node_modules/react/cjs/react.development.js:593
cloneElementWithValidation [as cloneElement]
node_modules/react/cjs/react.development.js:1415
formatElements
node_modules/@lingui/react/cjs/react.development.js:311
Trans.getTranslation
node_modules/@lingui/react/cjs/react.development.js:419
Trans.render
node_modules/@lingui/react/cjs/react.development.js:427
finishClassComponent
node_modules/react-dom/cjs/react-dom.development.js:13193
updateClassComponent
node_modules/react-dom/cjs/react-dom.development.js:13155
beginWork
node_modules/react-dom/cjs/react-dom.development.js:13824
performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:15863
workLoop
node_modules/react-dom/cjs/react-dom.development.js:15902
HTMLUnknownElement.callCallback
node_modules/react-dom/cjs/react-dom.development.js:100
invokeGuardedCallbackDev
node_modules/react-dom/cjs/react-dom.development.js:138
invokeGuardedCallback
node_modules/react-dom/cjs/react-dom.development.js:187
replayUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:15310
renderRoot
node_modules/react-dom/cjs/react-dom.development.js:15962
performWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js:16560
performWork
node_modules/react-dom/cjs/react-dom.development.js:16482
performSyncWork
node_modules/react-dom/cjs/react-dom.development.js:16454
requestWork
node_modules/react-dom/cjs/react-dom.development.js:16354
scheduleWork$1
node_modules/react-dom/cjs/react-dom.development.js:16218
scheduleRootUpdate
node_modules/react-dom/cjs/react-dom.development.js:16785
updateContainerAtExpirationTime
node_modules/react-dom/cjs/react-dom.development.js:16812
updateContainer
node_modules/react-dom/cjs/react-dom.development.js:16839
ReactRoot../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render
node_modules/react-dom/cjs/react-dom.development.js:17122
(anonymous function)
node_modules/react-dom/cjs/react-dom.development.js:17262
unbatchedUpdates
node_modules/react-dom/cjs/react-dom.development.js:16679
legacyRenderSubtreeIntoContainer
node_modules/react-dom/cjs/react-dom.development.js:17258
render
node_modules/react-dom/cjs/react-dom.development.js:17317

To Reproduce

A minimal working example can be cloned from here: https://github.com/tiguchi/lingui-undefined-error

In short here's a snippet that would cause the bug:

import { Trans } from "@lingui/react"

export default function App() {
   return <Trans id="someId">To get started, edit <code>src/App.js</code> and save to reload.</Trans>
}

Expected behavior

  • If id for <Trans> element is given no error should appear. Instead the correctly translated and HTML-formatted text should appear
  • If id is omitted then the <Trans> element should contain the HTML-formatted translated text instead of being blank.

Additional context

  • App created with create-react-app
  • Further installation and setup according to Lingui documentation at https://lingui.github.io/js-lingui/tutorials/react.html#installing-jslingui
  • jsLingui version 2.3.0
  • Babel version: I tried with the latest 7.0.0 beta 55 (installed via NPM) and also with latest stable installed via Yarn: 6.26.3
  • Babel config:
{
  "presets": [
    "env",
    "react",
    "@lingui/babel-preset-react"
  ]
}
  • Lingui Config:
{
  "fallbackLocale": "en",
  "sourceLocale": "en",
  "localeDir": "src/locale",
  "srcPathDirs": [
    "src"
  ],
  "srcPathIgnorePatterns": [
    "/node_modules/"
  ],
  "format": "lingui"
}
🌱 create-react-app

Most helpful comment

Hey @tiguchi,
unfortunately jsLingui babel plugins doesn't work with create-react-app 1.x without ejecting. The reason is that react-scripts, which builds your project, aren't using .babelrc from the root of your repository, so you can't extend the configuration.

The good news is that with upcoming create-react-app 2.x, jsLingui will work out of the box, because CRA 2.x uses babel macros.

What options do you have

  1. Use jsLingui without babel plugins and presets - it means you have to do the work manually:
// Replace:
<Trans id="someId">To get started, edit <code>src/App.js</code> and save to reload.</Trans>

// ...with this.
<Trans 
    id="someId"
    defaults="To get started, edit <0>src/App.js</0> and save to reload."
    components={[<code />]}
/>
// That's actually exactly what plugin does.

I replaced all inline HTML markup with indexed tags <0> and added components prop which an array of all components used in message (index of component in array corresponds to the index of tag in message)

The advantage of this solution is that you don't have to eject and you messages will look the same after you upgrade to CRA 2.x in the future.

  1. Eject and "@lingui/babel-preset-react" to .babelrc as you did

  2. Install beta version of CRA and wait for a release of jsLingui 3.0 which I'm planning to next week. That's gonna work very smooth, but using beta version of CRA might be a bit unstable. (They're waiting for a release of Babel 7. Lot of good things comming in)

All 3 comments

Hey @tiguchi,
unfortunately jsLingui babel plugins doesn't work with create-react-app 1.x without ejecting. The reason is that react-scripts, which builds your project, aren't using .babelrc from the root of your repository, so you can't extend the configuration.

The good news is that with upcoming create-react-app 2.x, jsLingui will work out of the box, because CRA 2.x uses babel macros.

What options do you have

  1. Use jsLingui without babel plugins and presets - it means you have to do the work manually:
// Replace:
<Trans id="someId">To get started, edit <code>src/App.js</code> and save to reload.</Trans>

// ...with this.
<Trans 
    id="someId"
    defaults="To get started, edit <0>src/App.js</0> and save to reload."
    components={[<code />]}
/>
// That's actually exactly what plugin does.

I replaced all inline HTML markup with indexed tags <0> and added components prop which an array of all components used in message (index of component in array corresponds to the index of tag in message)

The advantage of this solution is that you don't have to eject and you messages will look the same after you upgrade to CRA 2.x in the future.

  1. Eject and "@lingui/babel-preset-react" to .babelrc as you did

  2. Install beta version of CRA and wait for a release of jsLingui 3.0 which I'm planning to next week. That's gonna work very smooth, but using beta version of CRA might be a bit unstable. (They're waiting for a release of Babel 7. Lot of good things comming in)

@tricoder42 Thank you for the detailed explanation and workaround!

No worries! I'm closing this one until CRA 2.0 is released. Cheers 👍

Was this page helpful?
0 / 5 - 0 ratings

Related issues

landsman picture landsman  ·  5Comments

gitschwifty picture gitschwifty  ·  3Comments

LFDMR picture LFDMR  ·  4Comments

charliedavison picture charliedavison  ·  3Comments

andys8 picture andys8  ·  5Comments