1

This is all about having translation text strings and implementing them in JSX.

Lets say I have two strings. One for english and another for spanish like this:

English

const phrase = `this is just a string with some [replace]weird[/replace] link inside`

Spanish

const phrase = `esto es solo un string con un [replace]raro[/replace] enlace dentro`

When I am in English mode the string will of course come as the first example.

I am trying to replace the [replace]word inside[/replace] with a component like this.

<p dangerouslySetInnerHTML={{
    __html: phrase.replace(/\[replace\](.*)\[\/replace\]/, <Link to={linkurl} >test</Link>)
}}>

The output is: this is just a string with some [object Object] link inside

This one works fine, using just plain html tags

<p dangerouslySetInnerHTML={{
    __html: phrase.replace(/\[replace\](.*)\[\/replace\]/, "<b>$1</b")
  }}>
</p>

the output is: this is just a string with some weird link inside

I've also tried the following:

<p dangerouslySetInnerHTML={{
    __html: phrase.replace(/\[replace\](.*)\[\/replace\]/, "<Link to=\""+linkurl+"\">$1</Link>")
  }}>
</p>

the output is: this is just a string with some weird link inside

but the word 'weird' should be a link element, and it's not...

By the way the component is just a component from gatsby, it allows you to navigate with routing (currently using reach router).

zebnat
  • 521
  • 3
  • 13
  • The problem is JSX code `test` will get converted to `React.CreateElement(...)` and it's in the end indeed the object, which you can see as the result. Check: https://stackoverflow.com/questions/19266197/reactjs-convert-to-html or maybe google for `react to html` – Oleksandr Fedotov Nov 11 '18 at 19:20
  • the question is, why do you need to add a JSX object in the variable? It would be easier to try to add the component and just replace either the url, or the text, or whatever. Is there a specific use case that you have so we can suggest an alternative? – c-chavez Nov 11 '18 at 19:32
  • @c-chavez I can agree with the argument, on the other hand sometimes you really need to replace JSX with static markup. Here is more info to the topic: https://medium.com/@arkadiusz.machalica/how-to-render-static-markup-with-react-e0d192ac3a8c – Oleksandr Fedotov Nov 11 '18 at 19:35
  • @c-chavez these strings come from a db, translated by other ppl (i just used a random phrase here as example). Sometimes you need a hyperlink in between the words of a phrase or pharagraph that varies depending on the language, so we just use simple template format and then replace it with the proper html code. But we are talking with React+Gatsby here. – zebnat Nov 11 '18 at 21:44
  • I managed to "make it work", at least make it render the anchor from the gatsby component by using `ReactDOMServer.renderToString(anchor) but Reach Router from Gatsbyjs is not picking up the Link with JS, so everytime i click the link it reloads the entire page instead of navigating with js... it can render the anchor element w/o problems. – zebnat Nov 11 '18 at 21:45

1 Answers1

1

This is pretty easy to do if you treat your text templates as Markdown:

  1. Replace keywords with Markdown link syntax ([linked phrase](https://www.example.com/))
  2. Run the markdown through markdown-to-jsx to convert it to JSX
  3. Use the overrides option to use a custom component with a tags (e.g. a wrapper that extracts the href and provides it as the to prop on Gatsby's Link).

If you want a leaner pipeline, you could piece something together with dangerouslySetInnerHTML but it won't be as flexible or easily sanitized.

Example code:

import * as React from "react"
import Link from "gatsby"
import Markdown from "markdown-to-jsx"

const MagicText = ({ children, linkUrl }) => (
  <Markdown
    options={{
      overrides: {
        replace: Link,
      },
    }}
  >
    {children
      .replace("[replace]", `<replace to=${linkUrl}>`)
      .replace("[/replace]", "</replace>")}
  </Markdown>
)

And in use:

<MagicText linkUrl="https://www.example.com/">{phrase}</MagicText>
coreyward
  • 77,547
  • 20
  • 137
  • 166
  • I'm glad you understood my problem! This solution looks neat. I will try that in a few hours and see if it works like charm – zebnat Nov 13 '18 at 14:14