Reputation: 209
I am trying to do a simple test and I know I am missing something simple.
I have two applications, one hosted on node (localhost:3000) and another is hosted on another site (http://development.azure). The section site is not running under node, its standard IIS.
In my node server application i have the following
import { renderToString } from "react-dom/server"
app.get("/", (req, res) => {
const name = 'Marvelous Peter'
res.write("<!DOCTYPE html><html><head><title>My Page</title></head><body>");
res.write("<div id='content'>");
res.write(renderToString(<Hello name={name} />));
res.write("</div></body></html>");
res.end();
});
app.listen(3000)
In my IIS application I am attempting to load the react component using xhr and then hydrate it.
const xhr = require("xhr");
xhr({
method: "GET",
uri: "http://localhost:3000",
}, (err, resp, body) => {
// check resp.statusCode
ReactDOM.hydrate(body, document.getElementById("test"), () => {
});
});
I am seeing the output on my page, however, it is not HTML encoded. I renders as text
<!DOCTYPE html><html><head><title>My Page</title></head><body><div id='content'><div data-reactroot=""><h1>Hello, <!-- -->Marvelous Peter<!-- -->!</h1></div></div></body></html>
I tried returning only the renderToString value and not HTML and still get the same thing, specifically since i have tags in the component
import React from 'react'
const Hello = (props) => (
<div><h1>Hello, {props.name}!</h1></div>
)
export default Hello
I know I am missing something, but I am finding it hard to find info on doing this and would appreciate any help!
Thanks in advance!
EDIT:
Per the suggestion below, I tried to create a simple component and then hydrate it but I still get the same response.
Here is the new component:
import * as React from "react";
import * as ReactDOM from "react-dom";
class Hello extends React.Component {
public load() {
const xhr = require("xhr");
let res = null;
xhr({
method: "get",
sync: true,
uri: "http://localhost:3000"
}, (err, resp, body) => {
res = body;
});
return res;
}
public render(): JSX.Element {
const val = this.load()
return val;
}
}
const target: any = document.querySelector("#main");
if (target) {
ReactDOM.hydrate(<Hello />, target);
}
I am rather stumped right now. Could it have to do with the response header type from the xhr request?
Any suggestions?
Upvotes: 1
Views: 2196
Reputation: 1
I still don't have enough reputation to comment on your main question, but have you tried setting the response content-type in express as 'text/html'?
import { renderToString } from "react-dom/server"
app.get("/", (req, res) => {
const name = 'Marvelous Peter'
res.setHeader('content-type', 'text/html'); // add this line
res.write("<!DOCTYPE html><html><head><title>My Page</title></head><body>");
res.write("<div id='content'>");
res.write(renderToString(<Hello name={name} />));
res.write("</div></body></html>");
res.end();
});
app.listen(3000)
Usually browsers will only understand that they need to render the incoming data as html if this header is specified.
Upvotes: 0
Reputation: 6571
JSX !== HTML they may appear the same but they are fundamentally different and cannot be used interchangeably.
<div/>
in JSX is React.createElement("div");
<div></div>
in HTML is document.createElement("div");
You cannot use HTML (or a HTML string) in place of a function in React that expects JSX (mainly ReactDOM.hydrate, ReactDOM.render, React.createElement("div", null, NEED JSX HERE).
In order to render it not as a string you'll have to use the only API implementation that React provides to turn a HTML string into something resembling JSX which is...
dangerouslySetInnerHTML={{__html: YOUR STRING HERE}}
try this..
ReactDOM.render(<div dangerouslySetInnerHTML={{__html: YOURSTRINGHERE}}/>, document.body)
Upvotes: 3
Reputation: 3496
It's expects an Element, not a string.
ReactDOM.hydrate(
<MyComponent />,
document.getElementById('root')
)
Take that HTML response and create a react component out of it. Then pass it in your .hydrate
method.
Upvotes: 0