Hydrate JSX-Templates on the Client
See original GitHub issueHi Dennis! 😃
Is your feature request related to a problem? Please describe. We’ve been using UIEngine with the JSX-Adapter. So far, the Adapter renders the JSX-Code into static html and outputs them. This is fine for simple components that only receive props and don’t offer much interactivity, yet we run into trouble once there is functionality that is supposed to run on the client.
Describe the solution you’d like To support client-side functionality we would need to move from “using JSX as a templating engine” to also “hydrate the components on the client”. I’m not really sure how to go about this to be honest.
Let’s consider the following, simple component:
import React, { Component } from 'react'
class Heading extends Component {
componentDidMount() {
console.log('component says hi')
}
render() {
return (
<h1>Hello World</h1>
)
}
}
export default Heading
From what I understand, the JSX-Adapter is applied on every variant, and each variant (or rather the output for it) is separate from all other components/variants in its own html-file. When reading about this subject it appears that - in order to cause hydration for a component - you’d need to call:
const app = document.getElementById( "app" )
ReactDOM.hydrate( <Element /> , app )
Now, to bring these two points together, my impulse is that the JSX-Adapter is the right place to generate this code since it’s the only part that knows which component it is currently rendering and therefore needs to hydrate on the client.
And this is where I begin to wonder. Of course, If i just put the code into a template-literal and output it as a script-tag on the client, it won’t work since the Browser doesn’t know about React or JSX.
So, I tried transpiling the template-literal itself with babel:
let Element = require(filePath)
const code = `
const Element = ${Element}
const app = document.getElementById( "app" )
ReactDOM.hydrate( <Element /> , app )
`
const transformed = await babel.transformAsync(code, {
filename: filePath,
})
const hydration = transformed.code
return (
html +
`
<script type="text/javascript">
${hydration}
</script>
`
)
Unfortunately, the output now contains code like
var _react2 = _interopRequireDefault(require("react"));
…which the browser doesn’t understand either because of the require
.
At this point it starts to feel like a rabbit hole for me and I’m no longer sure whether this is the right direction to go.
Do you have any opinion on how to tackle this problem?
Regards, René
Issue Analytics
- State:
- Created 4 years ago
- Comments:11 (6 by maintainers)
Top GitHub Comments
I have a proof of concept working for Vue.js and I will publish an early draft once I finish the tests including a React example. This won’t be production ready from the get-go, but we can use it to work the kinks out. (i.e. property extraction etc. will need to be added, as the adapter doesn’t know anymore which kind of templating engine is used as webpack handles all of that in this case)
I hope to have something up by the end of this week so that we can try and progress it together.
Great, it’s working now, thanks for the quick response!