8

I'm trying to get react context working with SSR. This is what I have

// server/index.s

import express from "express";
import serverRenderer from "./middleware/renderer";
const PORT = 3000;
const path = require("path");
const app = express();
const router = express.Router();
router.use("^/$", serverRenderer);

app.use(router);
app.listen(PORT, error => {
  console.log("listening on 3000 from the server");
  if (error) {
    console.log(error);
  }
});

This is what the renderer looks like-

export default (req, res, next) => {
  const filePath = path.resolve(__dirname, "..", "..", "..", "index.html");
  fs.readFile(filePath, "utf8", (err, htmlData) => {
    if (err) {
      console.log("err", err);
      return res.status(404).end();
    }
    const store = configureStore();
    store.dispatch(getDesktopFooter(`${req.url}`)).then(data => {
      const preloadedState = store.getState();
      const TestContext = React.createContext({
        hello: "hello"
      });
      const renderedBody = ReactDOMServer.renderToStaticMarkup(
        <TestContext.Provider value={{ hello: "hello" }}>
          <DummyApp />
        </TestContext.Provider>
      );

      // const renderedBody = "";
      //render the app as a string
      const helmet = Helmet.renderStatic();

      //inject the rendered app into our html and send it
      // Form the final HTML response
      const html = prepHTML(htmlData, {
        html: helmet.htmlAttributes.toString(),
        head:
          helmet.title.toString() +
          helmet.meta.toString() +
          helmet.link.toString(),
        body: renderedBody,
        preloadedState: preloadedState
      });

      // Up, up, and away...
      return res.send(html);
    });
  });
};

My DummyApp looks like

import React from "react";
import Test from "./Test";
import { default as AppStyles } from "./App.css";
export default class DummyApp extends React.Component {
  render() {
    console.log("DUMMY APP CONTEXT");
    console.log(this.context);
    return (
      <React.Fragment>
        <div className={AppStyles.base}>
          <Test />
        </div>
      </React.Fragment>
    );
  }
}

The context is always {}, when it should be {hello: "hello"}

Why is this happening?

3
  • You don't seem to have a context Consumer in your DummyApp. Commented Mar 14, 2019 at 8:46
  • But the docs say I don't need one?reactjs.org/docs/context.html#dynamic-context Commented Mar 14, 2019 at 8:51
  • That example you linked is setting the contextType of the component, which you are not doing either. Commented Mar 14, 2019 at 8:52

2 Answers 2

4

You need to consume the context in your component for it to be able to read it.

You also need to create the TestContext outside of the server render function so that your component can import it and consume it.

Example

// TestContext.js
export default TestContext = React.createContext({
  hello: "hello"
});

// server.js
const TestContext = require("./TestContext.js")

export default (req, res, next) => {
  // ...
  const renderedBody = ReactDOMServer.renderToStaticMarkup(
    <TestContext.Provider value={{ hello: "hello" }}>
      <DummyApp />
    </TestContext.Provider>
  );
  // ...
};

// DummyApp.js
import TestContext from "./TestContext.js";

export default class DummyApp extends React.Component {
  static contextType = TestContext;

  render() {
    console.log(this.context);
    return (
      <React.Fragment>
        <div className={AppStyles.base}>
          <Test />
        </div>
      </React.Fragment>
    );
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1

So @Tholle was technically correct, but there was another issue that was the real problem. There wasn't much out there on this, so if someone faces the same problem, I hope they read this answer.

contextType only works for when the react version is >= 16.6.0.

This isn't mentioned in the react docs - https://reactjs.org/docs/context.html#classcontexttype, but weirdly is mentioned here

https://scotch.io/bar-talk/whats-new-in-react-166

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.