我是学习使用Node-Express-React创建Web服务器应用程序的新手,但我无法完全React。在本代码中我尝试使用
React中的componentDidMount()
函数,但不知怎的,这段代码没有触发它。搜索了所有的方式到Internet,但无法找到一种方法只使用Express Node和React。已经了解了Webpack
最终会在我的代码中创建复杂性
以下是设置我的观点和内容的服务器端server.js
代码
const express = require('express');
const app = express();
const path = require('path');
const React = require('react');
//setting my CSS folder (works fine)
app.use(express.static('static_assets'));
app.set('views','./views' );
app.set('view engine','jsx');
app.engine('jsx',require('express-react-views').createEngine());
app.get('/',function (req,resp){
resp.render('app',{});
});
app.listen(5000,function(){
console.log("Server Running at 5000");
});
这是我的React app.jsx
代码
var React =require( 'react');
class Text extends React.Component{
constructor(props){
super(props);
this.state = {speed:10};
}
componentDidMount(){
this.setState({speed:30});
}
render(){
return(
<div>
<h1>Hello </h1>
{this.state.speed}
</div>
);
}
}
class app extends React.Component{
constructor(props){
super(props);
}
render(){
return(
<Text />
);
}
}
module.exports= app;
我使用了相同的React端代码并从头开始创建了一个HTML网页并将其复制到那里并导入React.js
和ReactDOM.js
CDN,这个相同的代码在静态HTML页面上工作正常但是由于某种原因不在Express Node Server上
如果有任何方法可以使componentDidMount()
触发或在渲染后进行状态更改?
答案 0 :(得分:2)
我相信您的问题是因为您没有使用Webpack或其他内容来转换或捆绑您的代码,您使用React 它从未加载到页面上。没有ReactDOM.render()
或任何实际使用React所需的东西。您正在使用express-react-views
,它仅用作Express的jsx视图引擎。
来自README
:
这是一个Express视图引擎,它在服务器上呈现React组件。它呈现静态标记,不支持支持在客户端上安装这些视图。
React实际上并不在页面上,因此永远不会调用您的组件生命周期方法。基本上,它采用的是首先渲染的组件,并将其作为HTML提供给浏览器。
答案 1 :(得分:0)
正如Mark所说,您实际上并未在网页中呈现React组件,而是由jsx
模板引擎生成的简单HTML标记。首先,我们将您的模板引擎更改为更常规的hjs
。然后,为了使您的Web应用程序与React应用程序完全相同,我们需要在页面上安装React
然后安装您的组件。除此之外,我们还将使用node
在服务器上呈现我们的组件并将其发送到客户端。因此,我们将进行服务器端渲染,此外我们还将在您的Web应用程序中安装组件,以便您的生命周期方法可以运行。
•此处要注意的关键点是组件将在服务器上呈现,但在实际安装在浏览器中之前不会安装。
•需要注意的另一个关键点是没有DOM 操作会发生,因为已经在服务器上呈现了相同的标记,并使用{{1}将其移交给react-root内的客户端}。因此差异将导致零更改,整体渲染将很快。 这是一个相当简单的解决方案,您不必修改太多代码。
您的{{react}}
应该这样。
app.js
您的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'})
});
});
应该是这样的。
views/index.hjs
最后,您的组件 <!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/react@15/dist/react.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@15/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>
应如下所示。请注意App.jsx (public/jsx/App.jsx)
标志来修改我们的全局变量,因为相同的代码将在浏览器和服务器中运行。
isNode
了解有关使用here中的browserify进一步优化客户端代码的详情。
您还可以插入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'))
}
和react-router
,以获得更好的服务器端渲染React组件。 (如果你计划当然使用那些)
然而,现在这个答案会让这个答案太长,而且已经很长了。
真的希望它有所帮助!
答案 2 :(得分:0)
我的问题是,当我尝试在上面的代码中使用Express React View Template引擎时,React的生命周期方法没有被完全调用。问题是我尝试使用这个简单的模板加载所有React代码。它只加载所有HTML。我没有查看官方的React Docs of Installation我的答案就在那里。感谢 Mark Rabey的答案让我意识到我做错了什么。根据链接https://facebook.github.io/react/docs/installation.html的官方文档解决了我的问题。安装正确反应的主要文本是:
您无需重写应用即可开始使用React。
我们建议将React添加到应用程序的一小部分,例如 一个单独的小部件,因此您可以看到它是否适合您的使用 情况下。
虽然可以在没有构建管道的情况下使用React,但我们建议您进行设置 这样你就可以提高工作效率。通常是现代构建管道 包括:
包管理器,例如Yarn或npm。它可以让你利用 一个庞大的第三方包生态系统,易于安装或者 更新它们
捆绑包,例如webpack或Browserify。它可以让你编写模块 代码并将它们捆绑在一起形成小包,以优化加载时间。
像Babel这样的编译器。它允许您编写现代JavaScript代码 仍旧适用于旧浏览器。
这让我意识到我的代码中缺少的东西是WebPack或Broserify,我必须删除express-react-view
以使My React完全正常工作。感谢RemarkableMark的帮助指导我逐步在此PlayList上设置My React(https://www.youtube.com/watch?v=k66bOHX8MnY&list=PLVgOtoUBG2md5HxaABCcnfstF88CPzUeD)我已成功创建了自己的模板,并在Express上与Express-Node连接成功。你可以从这个Github链接获取它github.com/Ahsan-J/FirstExpressReactNodeLoginApp/tree/master/Express-React-Webpack。感谢所有Stack社区帮助解决我的第一个问题:')