React SSR-客户端上未定义的React Router Dom staticContext

时间:2020-03-07 07:15:35

标签: reactjs create-react-app react-router-dom

我正在使用带有服务器端渲染功能的React创建博客应用程序。我使用Create React App创建应用程序。

我遇到一个问题,即我的服务器数据被渲染一秒钟,然后在React接管渲染过程后消失了。我正在使用React Router Dom将数据从服务器传递到客户端react。基本上,我是按照本教程创建应用程序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 Server入口点index.js

require("ignore-styles");

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

require("./server");

客户端反应index.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反应App.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
    }

}

0 个答案:

没有答案