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.info("listening on 3000 from the server");
  if (error) {
    console.info(error);
  }
});

Вот как выглядит рендерер

export default (req, res, next) => {
  const filePath = path.resolve(__dirname, "..", "..", "..", "index.html");
  fs.readFile(filePath, "utf8", (err, htmlData) => {
    if (err) {
      console.info("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.info("DUMMY APP CONTEXT");
    console.info(this.context);
    return (
      <React.Fragment>
        <div className = {AppStyles.base}>
          <Test />
        </div>
      </React.Fragment>
    );
  }
}

Контекст всегда {}, когда он должен быть {hello: "hello"}

Почему это происходит?

Кажется, у вас нет контекста Consumer в вашем DummyApp.

Tholle 14.03.2019 09:46

Но в документах написано, что он мне не нужен?reactjs.org/docs/context.html#dynamic-context

praks5432 14.03.2019 09:51

В приведенном вами примере устанавливается contextType компонента, чего вы также не делаете.

Tholle 14.03.2019 09:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
6
3
5 603
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно использовать контекст в вашем компоненте, чтобы он мог его прочитать.

Вам также необходимо создать функцию 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.info(this.context);
    return (
      <React.Fragment>
        <div className = {AppStyles.base}>
          <Test />
        </div>
      </React.Fragment>
    );
  }
}

Итак, @Tholle был технически правильным, но была еще одна проблема, которая была настоящей проблемой. Об этом было немного, поэтому, если кто-то столкнется с той же проблемой, я надеюсь, что они прочитают этот ответ.

contextType работает только тогда, когда версия реакции >= 16.6.0.

Это не упоминается в документах по реакции - https://reactjs.org/docs/context.html#classcontexttype, но странным образом упоминается здесь

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

Другие вопросы по теме