zoxon
2/9/2018 - 9:55 AM

The basics for delivering HTML content to a React component from a Node/Express Server

The basics for delivering HTML content to a React component from a Node/Express Server

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;
"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}`);
});
// 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} />
// 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} />
    );
  }
}
// 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;