React Context无法与服务器端渲染一起使用

时间:2019-03-14 08:43:35

标签: reactjs react-context

我正在尝试使响应上下文与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"}

为什么会这样?

2 个答案:

答案 0 :(得分:1)

您需要使用组件中的上下文才能使其能够读取。

您还需要在服务器渲染功能之外创建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>
    );
  }
}

答案 1 :(得分:0)

所以@Tholle在技术上是正确的,但是还有另一个问题是真正的问题。那里没有太多内容,因此,如果有人遇到相同的问题,我希望他们阅读此答案。

contextType仅适用于反应版本> = 16.6.0

react docs-https://reactjs.org/docs/context.html#classcontexttype中未提及,但这里奇怪地提到了

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