Я создаю приложение для ведения блога, используя 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
}
}