Wie Mark sagte, Sie sind nicht tatsächlich Render-Komponente in Ihrer Webseite, sondern eine einfache HTML-Markup von der jsx
Templating-Engine generiert. Zuerst ändern wir Ihren Templating-Engine zu einem konventionelleren wie hjs
. Damit sich Ihre Webanwendung genau wie eine React-App verhält, müssen Sie auf der Seite React
installieren und dann Ihre Komponente mounten. Abgesehen davon verwenden wir auch node
, um unsere Komponente auf dem Server zu rendern und diese an den Client zu senden. Wir werden also Server-Side-Rendering durchführen, und wir werden auch Komponenten in Ihrer Web-App bereitstellen, damit Ihre Lebenszyklus-Methoden ausgeführt werden können.
• Der wichtigste Punkt hier ist, dass die Komponente auf dem Server gerendert wird, aber wird nicht montiert, bevor es tatsächlich in den Browser montiert ist.
• Ein weiterer wichtiger Punkt wird zu beachten sein, dass keine DOM Manipulationen, da die gleiche Markup bereits auf dem Server gerendert wurde, auftreten und {{react}}
mit reagieren Wurzel innerhalb an den Client übergeben.So wird das diff null Änderungen ergeben und das gesamte Rendering wird schnell sein. Dies ist eine ziemlich einfache Lösung und Sie müssen nicht viel Code ändern.
Ihre app.js
sollte dies mögen.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var React = require('react');
var ReactDOM = require('react-dom/server');
// Will allow us to require .jsx files and to compile them.
var jsx = require('node-jsx');
jsx.install();
var HelloMessageComponent = require('./public/jsx/App.jsx');
var HelloMessage = React.createElement(HelloMessageComponent);
var app = express();
// view engine setup. Change this to hjs.
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', function (req, res) {
res.render('index', {
react: ReactDOM.renderToString(HelloMessage, {name: 'John'})
});
});
Ihre views/index.hjs
sollte so.
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<!-- Notice we're installing React here too via CDN. This will mount our already pre-rendered components -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<script crossorigin src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
<script crossorigin src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
</head>
<body>
<!-- This is where our server side rendered component code will go. -->
<div id="react-root">{{react}}</div>
<!-- Mount the same component inside the App.jsx file from the browser. -->
<script src="/jsx/App.jsx" type="text/babel"></script>
<!-- The server will create a full static markup inside the react-root div. -->
<!-- Once we go to localhost:3000 from our browser the above script will run and mount the same component inside -->
<!-- the same div. The key here is that no DOM manipulations will occur since the same markup has already been rendered -->
<!-- inside react-root using {{react}}. So diff will result in zero changes and the rendering will be fast. -->
<!-- Your React app is now mounted as well as rendered from the server. -->
<!-- You can of course further optimize your text/babel script tag by using browserify to precompile and bundle. -->
<!-- The link for bundling is down below! -->
</body>
</html>
Schließlich Ihre Komponente App.jsx (public/jsx/App.jsx)
sollte wie folgt aussehen. Bitte beachten Sie das isNode
Flag, um unsere globalen Variablen zu ändern, da derselbe Code innerhalb des Browsers und des Servers ausgeführt wird.
var isNode = typeof module !== 'undefined' && module.exports
, React = isNode ? require('react') : window.React
, ReactDOM = isNode ? require('react') : window.ReactDOM;
class HelloMessage extends React.Component {
constructor(props) {
super(props);
this.state = {
name: this.props.name
}
}
componentDidMount() {
console.log('mounted');
setTimeout(() => {
this.setState({name: 'Mustansir!'})
}, 5000);
}
handleClick() {
alert('clicked!');
}
render() {
return <div onClick={this.handleClick}>Hello {this.state.name}</div>;
}
}
if (isNode) {
module.exports = HelloMessage
} else {
ReactDOM.render(<HelloMessage name="John"/>, document.getElementById('react-root'))
}
Erfahren Sie mehr über weitere Ihrer Client-Seite Code browserify von here zu optimieren.
können Sie stecken auch in Ihren react-router
und react-redux
für eine noch bessere Serverseite Rendering Ihre Komponenten reagieren. (Wenn Sie planen, diese natürlich zu verwenden)
Das würde jedoch jetzt diese Antwort viel zu lange machen und es ist schon ziemlich lang.
Wirklich hoffe, es hilft!
Ich habe 'console.log()' verwendet, um zu überprüfen, ob es läuft oder nicht, und ich habe nichts erhalten, was eigentlich das nach bedeutet Rendering-Funktion wird nicht ausgelöst. Ich kopierte den Code in einem einfachen HTML und importierte CDNs von React in Skript-Tags und entdeckte, dass It 'componentDidMount()' läuft Fine. Aber der gleiche Code läuft nicht in einem Server Rendering –
Haben Sie versucht Create React App? https://github.com/facebookincubator/create-react-app –
'componentDidMount()' wird nach dem ersten 'render()' aufgerufen, so dass beim ersten Start der App 'state' nicht geändert wird bedeutet, dass Dinge nicht "montiert" wurden. Wenn Sie Ihre Anwendung das erste Mal starten, sehen Sie die Änderung von 'state' in' render() 'nicht. Wenn Sie später den Status ändern, können Sie das in 'render()' anzeigen. Sehen Sie sich den Reaktionslebenszyklus an und er wird Ihnen dabei helfen zu verstehen, wie react die Ansicht mit Backend-Daten aktualisiert: https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/tapping_into_componentwillupdate.html –