Repository: lingui/js-lingui
Pull request #799 (2020-10-31 04:29:07)

Allow null override for default component
the docs state that `render={null}` or `component={null}` should override the `defaultComponent` prop. (https://github.com/lingui/js-lingui/blame/v3.0.0/docs/ref/react.rst#L88)

suppose I had this

```ts
const Span = ({ children }) => {
    return <span>{children}</span>;
};

const App = () => {
    return (
        <I18nProvider i18n={i18n} defaultComponent={Span}>
            <Trans id='Hello' render={null} />
        </I18nProvider>
    );
};
```

current behaviour: `<App /> === <span>Hello</span>`
expected behaviour:`<App /> === 'Hello'`



vercel[bot]: This pull request is being automatically deployed with Vercel ([learn more](https://vercel.link/github-learn-more)).  
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: [https://vercel.com/lingui-js/js-lingui/kokrt5guy](https://vercel.com/lingui-js/js-lingui/kokrt5guy)  
✅ Preview: *In Progress*


codecov[bot]: # [Codecov](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=h1) Report
> Merging [#799](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=desc) into [main](https://codecov.io/gh/lingui/js-lingui/commit/7e321e3851ecc5494d3bd33d2f9621ace2a33347?el=desc) will **decrease** coverage by `0.13%`.
> The diff coverage is `0.00%`.

[![Impacted file tree graph](https://codecov.io/gh/lingui/js-lingui/pull/799/graphs/tree.svg?width=650&height=150&src=pr&token=CuJ1VD5BY5)](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##             main     #799      +/-   ##
==========================================
- Coverage   84.33%   84.20%   -0.14%     
==========================================
  Files          39       39              
  Lines        1264     1266       +2     
  Branches      332      333       +1     
==========================================
  Hits         1066     1066              
- Misses        116      117       +1     
- Partials       82       83       +1     
```


| [Impacted Files](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/react/src/Trans.tsx](https://codecov.io/gh/lingui/js-lingui/pull/799/diff?src=pr&el=tree#diff-cGFja2FnZXMvcmVhY3Qvc3JjL1RyYW5zLnRzeA==) | `71.42% <0.00%> (-5.50%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=footer). Last update [de7d07e...14cd84f](https://codecov.io/gh/lingui/js-lingui/pull/799?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

tricoder42: Hey @dhaigh, thanks for the bug fix! You're right. Could you also please provide a test? Just add relevant test cases to `rendering` section in `Trans.test.tsx`:

https://github.com/lingui/js-lingui/blob/de7d07e6004fe379d8a702c056496536a44a285c/packages/react/src/Trans.test.tsx#L139-L204
dhaigh: @tricoder42 i had a go, let me know what you think :) 

Patch:
diff --git a/packages/react/src/Trans.tsx b/packages/react/src/Trans.tsx
index 454dbfac..7809aa82 100644
--- a/packages/react/src/Trans.tsx
+++ b/packages/react/src/Trans.tsx
@@ -65,6 +65,10 @@ export function Trans(props: TransProps) {
     ? formatElements(_translation, components)
     : null
 
+  if (render === null || component === null) {
+    return translation
+  }
+
   const FallbackComponent = defaultComponent || React.Fragment
 
   // Validation of `render` and `component` props


Test patch:
diff --git a/packages/react/src/Trans.test.tsx b/packages/react/src/Trans.test.tsx
index 1cfb730f..e3c13b96 100644
--- a/packages/react/src/Trans.test.tsx
+++ b/packages/react/src/Trans.test.tsx
@@ -44,10 +44,10 @@ describe("Trans component", function () {
     const originalConsole = console.error
     console.error = jest.fn()
 
-    renderWithI18n(<Trans render="span" id="Just a text" />)
+    renderWithI18n(<Trans render="span" id="Some text" />)
     expect(console.error).toHaveBeenCalled()
 
-    renderWithI18n(<Trans render="span" id="Just a text" />)
+    renderWithI18n(<Trans render="span" id="Some text" />)
     expect(console.error).toHaveBeenCalledTimes(2)
     console.error = originalConsole
   })
@@ -56,7 +56,7 @@ describe("Trans component", function () {
     const originalConsole = console.error
     console.error = jest.fn()
 
-    renderWithI18n(<Trans render="div" component="span" id="Just a text" />)
+    renderWithI18n(<Trans render="div" component="span" id="Some text" />)
     expect(console.error).toHaveBeenCalled()
     console.error = originalConsole
   })
@@ -137,9 +137,9 @@ describe("Trans component", function () {
   })
 
   describe("rendering", function () {
-    it("should render just a text without wrapping element", function () {
-      const txt = html(<Trans id="Just a text" />)
-      expect(txt).toEqual("Just a text")
+    it("should render a text node with no wrapper element", function () {
+      const txt = html(<Trans id="Some text" />)
+      expect(txt).toEqual("Some text")
     })
 
     it("should render custom element", function () {
@@ -173,10 +173,34 @@ describe("Trans component", function () {
       }
       const span = render(
         <I18nProvider i18n={i18n} defaultComponent={ComponentFC}>
-          <Trans id="Just a text" />
+          <Trans id="Some text" />
         </I18nProvider>
       ).container.innerHTML
-      expect(span).toEqual(`<div>Just a text</div>`)
+      expect(span).toEqual(`<div>Some text</div>`)
+    })
+
+    it("should ignore defaultComponent when render is null", function () {
+      const ComponentFC: React.FunctionComponent = (props: { children?: React.ReactNode }) => {
+        return (<div>{props.children}</div>)
+      }
+      const translation = render(
+        <I18nProvider i18n={i18n} defaultComponent={ComponentFC}>
+          <Trans id="Some text" render={null} />
+        </I18nProvider>
+      ).container.innerHTML
+      expect(translation).toEqual("Some text")
+    })
+
+    it("should ignore defaultComponent when component is null", function () {
+      const ComponentFC: React.FunctionComponent = (props: { children?: React.ReactNode }) => {
+        return (<div>{props.children}</div>)
+      }
+      const translation = render(
+        <I18nProvider i18n={i18n} defaultComponent={ComponentFC}>
+          <Trans id="Some text" component={null} />
+        </I18nProvider>
+      ).container.innerHTML
+      expect(translation).toEqual("Some text")
     })
   })