Skip to content

Instantly share code, notes, and snippets.

@jtulk
Created June 3, 2017 05:38
Show Gist options
  • Save jtulk/324672c3769f60eb0334f1de82c5b115 to your computer and use it in GitHub Desktop.
Save jtulk/324672c3769f60eb0334f1de82c5b115 to your computer and use it in GitHub Desktop.
The basics for delivering HTML content to a React component from a Node/Express Server
// in my React Router Routes I'm going to handle each URL request with a
// component that serves up static content
// not a full file obviously
<Route name="cookies" path="/cookies" component={StaticContainer} />
<Route name="policy" path="/policy" component={StaticContainer} />
<Route name="terms-of-service" path="/terms-of-service" component={StaticContainer} />
"use strict";
const express = require("express");
const path = require("path");
// Google Cloud Defaults to 8080
const PORT = 8080;
const app = express();
// set up a template controller to serve the HTML fragments on /template routes
const templateController = require("./server/controllers/templateController");
app.use(express.static(path.join(__dirname, "public")));
// `use` will tell Express to default to the templateController for any URL request
// starting with /template
app.use("/template", templateController);
// for any other route default to serving up index.html (this will
// allow browserhistory routing with React Router v3)
app.use("/", (req, res) => {
res.status(200).sendFile(path.resolve(__dirname, "public", "index.html"));
});
app.listen(PORT, () => {
console.log(`App listening on ${PORT}`);
});
// a React Component that includes the header and footer
import React from "react";
import Header from "./../components/Header";
import Footer from "./../components/Footer";
import StaticContent from "./../components/StaticContent";
// use the route name from React Router to request the right data
const StaticContainer = ({ route }) => (
<div>
<Header />
<StaticContent content={route.name} />
<Footer />
</div>
);
export default StaticContainer;
// a react component to inject the returned html
import React, { Component } from "react";
import "whatwg-fetch";
export default class StaticContent extends Component {
state = {
__html: ""
}
componentWillMount() {
// fetch the HTML fragment with a local API request
fetch(`/template/${this.props.content}`)
.then(resp => {
// fetch returns a readable stream, so translate it into stringified HTML
return resp.text();
})
.then(content => {
// dangerouslySetInnerHTML requires using an object with an `__html` key
this.setState({
__html: content
});
})
.catch(err => {
// handle the error
});
}
render() {
return (
<div dangerouslySetInnerHTML={this.state} />
);
}
}
const express = require("express");
const path = require("path");
const templateController = new express.Router();
// an array of the static page names I'm going to serve up
const staticPages = [
"cookies",
"policy",
"terms-of-service"
];
// serve the HTML fragments from server/templates/[name].html
staticPages.forEach(page => {
tc.get(`/${page}`, (req, res) => {
res
.status(200)
.sendFile(path.join(__dirname, "..", "templates", `${page}.html`));
});
});
// I don't know if this is useful, but I want to throw a server error for
// requests to a non-configured endpoint
tc.get("*", (req, res) => {
res.status(500).json({
message: "This is not a working API endpoint"
});
});
module.exports = templateController;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment