React Context 不适用于服务器端渲染

React Context not working with server side rendering

我正在尝试让 React 上下文与 SSR 一起工作。这就是我的

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

这是渲染器的样子-

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);
    });
  });
};

我的 DummyApp 看起来像

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>
    );
  }
}

上下文总是 {},而应该是 {hello: "hello"}

为什么会这样?

您需要在组件中使用上下文才能读取它。

您还需要在服务器呈现函数之外创建 TestContext,以便您的组件可以导入并使用它。

例子

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

所以@Tholle 在技术上是正确的,但还有另一个问题才是真正的问题。这方面的内容不多,所以如果有人遇到同样的问题,我希望他们能阅读这个答案。

contextType 仅适用于 React 版本 >= 16.6.0.

React 文档中没有提到这一点 - https://reactjs.org/docs/context.html#classcontexttype,但奇怪的是这里提到了

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