How To Use Thymeleaf Th:text In ReactJS

- 1 answer

I am running a springboot application with Thymeleaf and reactJS. All the HTML text are read from by using th:text in the pages, but when I have th:text in reactJS HTML block, reactJS seems angry about it.

render() {
  return (
      <input type="text" th:text="#{home.welcome}">

The error is:

Namespace tags are not supported. ReactJSX is not XML.

Is there a walkaround besides using dangerouslySetInnerHTML?

Thank you!



There is no sane workaround.

You are getting this error because Thymeleaf outputs XML, and JSX parsers do not parse XML.

You did this because JSX looks very, very similar to XML. But they are very, very different, and even if you somehow hacked Thymeleaf to strip namespaced attributes and managed to get a component to render, it would be merely a fleeting moment of duct-taped-together, jury-rigged code that will fall apart under further use.

This is a really, really bad idea because JSX is Javascript. You are generating Javascript on the fly. Just to name a few reasons this will not work in the long term:

  • This makes your components difficult if not impossible to test.
  • Reasoning about application state will be a nightmare as you will struggle to figure out if the source of a certain state is coming from Thymeleaf or JS.
  • Your application will completely grind to a halt if Thymeleaf outputs bad JS.
  • These problems will all get worse with time (Thyme?) as as developers abuse the ease with which they can render server-side data to the client-side, leading to an insane application architecture.

Do not do this. Just use Thymeleaf, or just use React.

Sample Alternative: I primarily work on a React application backed by a Java backend. So I understand how someone could stumble upon this hybrid and think it might be a good idea. You are likely already using Thymeleaf and are trying to figure out how you can avoid rewriting your servlets but still get the power of React.

We were in a similar boat two years ago, except with an aging JSP frontend, but the difference is negligible. What we did (and it works well) is use a JSP page to bootstrap the entire React application. There is now one JSP page that we render to the user. This JSP page outputs JSON into a single <script> tag that contains some initial startup data that we would otherwise have to fetch immediately. This contains resources, properties, and just plain data.

We then output another <script> that points to the location of a compiled JS module containing the entire standalone React application. This application loads the JSON data once when it starts up and then makes backend calls for the rest. In some places, we have to use JSP for these, which is less than ideal but still better than your solution. What we do is have the JSP pages output a single attribute containing JSON. In this way (and with some careful pruning by our XHR library) we get a poor man's data interchange layer built atop a JSP framework we don't have time to change.

It is definitely not ideal, but it works well and we have benefited vastly from the many advantages of React. When we do have issues with this peculiar implementation, they are easy to isolate and resolve.