Created
June 3, 2017 05:38
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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}`); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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} /> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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