React SSR - React Router Dom static не определен на клиенте - PullRequest
1 голос
/ 07 марта 2020

Я создаю приложение для ведения блога, используя React с функцией рендеринга на стороне сервера. Я создаю приложение, используя Create React App.

Я сталкиваюсь с проблемой, когда мои данные, поступающие с сервера, обрабатываются в течение секунды, а затем исчезают после того, как реакция принимает процесс рендеринга. Я использую React Router Dom для передачи данных с сервера на клиент реагировать. По сути, я следую этому руководству, чтобы создать приложение https://www.youtube.com/watch?v=NwyQONeqRXA, но в видео отсутствует некоторая информация, например, получение данных в API. Поэтому я ссылаюсь на этот репозиторий для получения данных по API https://github.com/tylermcginnis/rrssr

Основываясь на собранных ресурсах, я получил следующие коды.

server. js

import express from "express";
import fs from "fs";
import path from "path";
import { StaticRouter, matchPath } from "react-router-dom";

import React from "react";
import ReactDOMServer from "react-dom/server";
import serialize from "serialize-javascript";
import App from "../src/App";
import routes from "../src/routes";

const app = express();

const PORT = 3001;

app.use(express.static(path.resolve(__dirname, "..", "build")));

app.get("*", (req, res, next) => {
    // point to the html file created by CRA's build tool
    const filePath = path.resolve(__dirname, "..", "build", "index.html");

    fs.readFile(
        path.resolve(filePath),
        "utf-8",
        (err, html_data) => {
            if (err) {
                console.error(err);
                return res.status(500).send(`Some error happened: ${err}`);
            }

            const activeRoute =
                routes.find(route => matchPath(req.url, route)) || {};

            const promise = activeRoute.fetchInitialData
                ? activeRoute.fetchInitialData(req.path)
                : Promise.resolve();

            promise
                .then(rawData => {
                    console.log('rawData', rawData[0]);

                    const context = { posts: rawData };

                    const markup = ReactDOMServer.renderToString(
                        <StaticRouter location={req.url} context={context}>
                            <App />
                        </StaticRouter>
                    );

                    return res
                        .status(200)
                        .send(
                            html_data
                                .replace(
                                    '<div id="root" class="container-fluid"></div>',
                                    `<div id="root" class="container-fluid">${markup}</div>`
                                )
                                .replace(
                                    "__INITIAL_DATA__={}",
                                    `__INITIAL_DATA__=${serialize(rawData)}`
                                )
                        );
                })
                .catch(next);
        }
    );
});

app.listen(PORT, () => {
    console.log(`App launched at http://localhost:${PORT}`);
});

Node JS Индекс точки входа сервера. js

require("ignore-styles");

require("@babel/register")({
    ignore: [/(node_modules)/],
    presets: ["@babel/preset-env", "@babel/preset-react"]
});

require("./server");

Индекс реакции клиента. js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.css";
import "./index.css";
import "./fonts/VarelaRound-Regular.ttf";

ReactDOM.hydrate(
    <BrowserRouter>
        <App post_data={window.__INITIAL_DATA__} />
    </BrowserRouter>,
    document.getElementById("root")
);

Приложение реагирования Clieant. js

import React, { Component } from "react";

import "./App.css";

import { Route, Link, Redirect, Switch } from "react-router-dom";
import routes from "./routes";


class App extends Component {
    render() {
        return (
            <div>
                <Switch>
                    {routes.map(
                        ({ path, exact, component: Component, ...rest }) => (
                            <Route
                                key={path}
                                path={path}
                                exact={exact}
                                render={props => (
                                    <Component {...props} {...rest} />
                                )}
                            />
                        )
                    )}
                </Switch>
            </div>
        );
    }
}

export default App;

Когда я пытаюсь вывести данные на компонент, он пропал, и теперь передача staticContext с сервера не определена. В чем здесь проблема? Мне не хватает конфигурации или библиотеки?

import React from "react";

export default class Home extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            posts: this.props.staticContext
                ? this.props.staticContext.posts
                : []
        };
        console.log("constructor", this.props); // STATIC CONTEXT UNDEFINED ON THIS OUTPUT
    }
    componentDidMount() {
        console.log("componentDidMount", this.props);// STATIC CONTEXT UNDEFINED ON THIS OUTPUT
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...