- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个在客户端和服务器(节点和express)上呈现的React应用程序。如果有人输入 url http://webaddress.com/products/1,我会尝试让渲染正常工作。如果我输入此内容并按 Enter 键(或刷新页面),应用程序就会崩溃,因为它不知道如何获取 url 中的 1 来解析并获取正确的产品。
如果我单击导航中链接到 products/1 的链接,应用程序将正常工作并显示正确的产品。
如何让 React-Router 从访问者在 http://webaddress.com/products/1 中输入的 URL 中获取 :productsId
(/products/1 中的 1)参数?
这是我的 server.js:
import express from 'express';
import http from 'http';
var PageNotFound = require('./js/components/PageNotFound.react');
import React from 'react';
import { renderToString } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import { routes } from './routes';
const app = express();
app.use(express.static('public'));
app.set('view engine', 'ejs');
/* We call match(), giving it the routes object defined above and the req.url, which contains the url of the request. */
app.get('*', (req, res) => {
// routes is our object of React routes defined above
match({ routes, location: req.url }, (err, redirectLocation, props) => {
if (err) {
// something went badly wrong, so 500 with a message
res.status(500).send(err.message);
} else if (redirectLocation) {
// we matched a ReactRouter redirect, so redirect from the server
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (props) {
// console.log("props on server.js: ", props);
// if we got props, that means we found a valid component to render
// for the given route. renderToString() from ReactDOM takes that RoutingContext
// component and renders it with the properties required.
const markup = renderToString(<RouterContext {...props} />);
// render `index.ejs`, but pass in the markup we want it to display
res.render('index', { markup })
} else {
// no route match, so 404. In a real app you might render a custom
// 404 view here
console.log("not found page");
res.sendStatus(404);
// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
}
});
});
const server = http.createServer(app);
app.set('port', (process.env.PORT || 3000))
app.get('/', (req, res) => {
var result = 'App is Running'
res.send(result);
}).listen(app.get('port'), () => {
console.log('App is running, server is listening on port', app.get('port'));
});
这是routes.js 文件:
import TopLevelContainerApp from './js/components/TopLevelContainerApp.react'
import Home from './js/components/Home.react';
import Product from './js/components/Product.react';
const routes = {
path: '',
component: SolidBroadheadApp,
childRoutes: [
{
path: '/',
component: Home
},
{
path: '/products/:productId',
component: Product
}
}
export { routes };
这是客户端渲染js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';
import { routes } from './../routes';
ReactDOM.render(
<Router routes={routes} history={browserHistory} />, document.getElementById('website-app')
);
这是 ProductStore.js:
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var articles = null;
var links = null;
var product = null;
function setArticles(receivedArticles) {
articles = receivedArticles;
return articles;
}
function setLinks(receivedLinks) {
links = receivedLinks;
return links;
}
function setProduct(productId) {
console.log("products store productId: ", productId);
function filterById(obj) {
return obj.id === productId;
}
var filteredArticlesArr = articles.filter(filterById);
product = filteredArticlesArr[0];
return product;
};
function emitChange() {
ProductsStore.emit('change');
}
var ProductsStore = assign({}, EventEmitter.prototype, {
addChangeListener: function(callback) {
this.on('change', callback);
},
removeChangeListener: function(callback) {
this.removeListener('change', callback);
},
getArticles: function() {
return articles;
},
getLinks: function() {
return links;
},
getProduct: function() {
return product;
}
});
function handleAction(action) {
switch (action.type) {
case 'received_products_articles':
setArticles(action.articles);
emitChange();
break;
case 'get_links':
setLinks(action.articles);
emitChange();
break;
case 'get_product':
setProduct(action.productId);
emitChange();
break;
}
}
ProductsStore.dispatchToken = AppDispatcher.register(handleAction);
module.exports = ProductsStore;
这是呈现特定产品的产品组件:
var React = require('react');
var ProductArticle = require('./products-solid-components/ProductArticle.react');
var ProductsStore = require('./../stores/ProductsStore');
// gets all the products
var ProductsArticlesWebUtilsAPI = require('./../../utils/ProductsArticlesWebUtilsAPI');
ProductsArticlesWebUtilsAPI.initializeArticles();
var Product = React.createClass({
getInitialState: function() {
return {
articles: ProductsStore.getArticles(),
product: ProductsStore.getProduct()
};
},
componentDidMount: function() {
ProductsStore.addChangeListener(this.onProductChange);
},
componentWillUnmount: function() {
ProductsStore.removeChangeListener(this.onProductChange);
},
onProductChange: function() {
this.setState({
articles: ProductsStore.getArticles(),
product: ProductsStore.getProduct()
});
},
render: function() {
if (this.state.articles)
if (this.state.product) {
return (
<div className="product">
<section className="container-fluid">
<ProductArticle name={this.state.product.name} largeImage={this.state.product.largeImage} description={this.state.product.description} />
</section>
);
} else {
return (
<div>Product is on the way</div>
);
}
}
});
module.exports = Product;
这是获取信息的文件:
var ProductsActionCreators = require('../js/actions/ProductsActionCreators');
var productArticles = [
{
"id": 1,
"name": "product 1",
"largeImage": "1.png",
"largeVideo": "1.mp4",
"description": "1 description",
},
{
"id": 2,
"name": "product 2",
"largeImage": "2.png",
"largeVideo": "2.mp4",
"description": "2 description",
},
{
"id": 3,
"name": "product 3",
"largeImage": "3.png",
"largeVideo": "3.mp4",
"description": "3 description",
},
];
var products = [];
function separateProductIdsAndNamesOut(productArticles) {
console.log("productArticles: " + productArticles);
products = productArticles.map(function(product) {
return { id: product.id, name: product.name };
});
return products;
}
function initializeArticles() {
return ProductsActionCreators.receiveArticles(productArticles);
}
// to build links in a nav component without payload of video and large img etc
function initializeProductsForNav() {
return ProductsActionCreators.receiveArticlesIdsAndNames(separateProductIdsAndNamesOut(productArticles));
}
module.exports = {
initializeArticles: initializeArticles,
initializeProductsForNav: initializeProductsForNav
};
更新:当我手动输入网址或在页面上点击刷新一次时,来自 server.js 的 console.log:
props on server.js: { routes:
[ { path: '', component: [Object], childRoutes: [Object] },
{ path: '/products/:productId', component: [Object] } ],
params: { productId: '4' },
location:
{ pathname: '/products/4',
search: '',
hash: '',
state: null,
action: 'POP',
key: '8b8lil',
query: {},
'$searchBase': { search: '', searchBase: '' } },
components:
[ { [Function] displayName: 'SolidBroadheadApp' },
{ [Function] displayName: 'Product' } ],
history:
{ listenBefore: [Function],
listen: [Function],
transitionTo: [Function],
push: [Function],
replace: [Function],
go: [Function],
goBack: [Function],
goForward: [Function],
createKey: [Function],
createPath: [Function],
createHref: [Function],
createLocation: [Function],
setState: [Function],
registerTransitionHook: [Function],
unregisterTransitionHook: [Function],
pushState: [Function],
replaceState: [Function],
isActive: [Function],
match: [Function],
listenBeforeLeavingRoute: [Function] },
router:
{ listenBefore: [Function: listenBefore],
listen: [Function: listen],
transitionTo: [Function: transitionTo],
push: [Function: push],
replace: [Function: replace],
go: [Function: go],
goBack: [Function: goBack],
goForward: [Function: goForward],
createKey: [Function: createKey],
createPath: [Function: createPath],
createHref: [Function: createHref],
createLocation: [Function: createLocation],
setState: [Function],
registerTransitionHook: [Function],
unregisterTransitionHook: [Function],
pushState: [Function],
replaceState: [Function],
__v2_compatible__: true,
setRouteLeaveHook: [Function: listenBeforeLeavingRoute],
isActive: [Function: isActive] } }
this.state.searchResult: null
this.state.productLinks in component: null
更新 2:我已删除 404 和 splat 路由,服务器 console.log 显示:
App is running, server is listening on port 3000
props.params on server.js: { productId: '4' } // looks good; proper productId is passed.
this.state.productLinks in component: null
this.props in product component: { productId: '4' } // looks good; should render properly
props.params on server.js: { productId: 'build.js' } // why is this assigned 'build.js' causing the problem???
this.state.productLinks in component: null
this.props in product component: { productId: 'build.js' } // why is this assigned 'build.js'? This is probably the cause of the problem.
该进程似乎运行了两次,第一次分配了正确的 id,第二次分配了由 webpack 构建的“build.js”? WTF。
显示 props 从 ProductId 重写为“build.js”的要点: https://gist.github.com/gcardella/1367198efffddbc9b78e
Webpack 配置:
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: path.join(process.cwd(), 'client/client-render.js'),
output: {
path: './public/',
filename: 'build.js'
},
module: {
loaders: [
{
test: /.js$/,
loader: 'babel'
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
APP_ENV: JSON.stringify('browser')
}
})
]
}
更新 3:我通过删除状态检查来修复双循环,但是在渲染服务器端时会失败,因为状态尚未设置。因此,我添加了一个检查来查看产品组件中是否存在 state.product:
var React = require('react');
var ProductArticle = require('./products-solid-components/ProductArticle.react');
var ProductPresentation = require('./products-solid-components/ProductPresentation.react');
var ProductLargeImage = require('./products-solid-components/ProductLargeImage.react');
var LargeLeftImageArticle = require('./reusable-tool-components/LargeLeftImageArticle.react');
var LargeRightImageArticle = require('./reusable-tool-components/LargeRightImageArticle.react');
var ProductsStore = require('./../stores/ProductsStore');
// if (process.env.APP_ENV === 'browser') {
var ProductsArticlesWebUtilsAPI = require('./../../utils/ProductsArticlesWebUtilsAPI');
ProductsArticlesWebUtilsAPI.initializeArticles();
// }
var Product = React.createClass({
getInitialState: function() {
return {
articles: ProductsStore.getArticles(),
product: ProductsStore.getProduct()
};
},
componentDidMount: function() {
ProductsStore.addChangeListener(this.onProductChange);
},
componentWillUnmount: function() {
ProductsStore.removeChangeListener(this.onProductChange);
},
onProductChange: function() {
this.setState({
articles: ProductsStore.getArticles(),
product: ProductsStore.getProduct()
});
},
render: function() {
console.log("this.props in product component: ", this.props);
// if (this.state.articles)
console.log("after check for this.state.product on component this.props.params.productId: ", this.props.params.productId);
if (this.state.product) {
return (
<div className="product">
<section className="container-fluid">
<ProductArticle name={this.state.product.name} largeImage={this.state.product.largeImage} description={this.state.product.description} />
</section>
</div>
);
} else {
console.log("no state");
return (
// if there is no state, how do I render something on the server side?
);
}
}
});
module.exports = Product;
最佳答案
事实证明这根本不是路由问题。不同领域存在很多问题:
我必须将 bundle.js
重命名为另一个名称,例如 client-bundle.js
。
然后我必须解决 ProductsStore 中的一个问题,以过滤产品数组以匹配 ProductId:
function setProduct(productId) {
var filteredProductsArr = products.filter(function(product) {
return product.id == productId;
});
product = filteredProductsArr[0];
return product;
};
然后我必须在我的产品组件的 componentDidMount() 中放置一个 Action 创建器:ProductsActionCreators.getProduct(this.props.params.productId);
所有这一切都像一个魅力:)
关于javascript - React 服务器端渲染 - 如何使用 :productId params passed in? 从服务器渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35338809/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!