【问题标题】:StaticRouter renders a leading slash for <Link> tags [react-router 4.0.0]StaticRouter 为 <Link> 标签呈现前导斜杠 [react-router 4.0.0]
【发布时间】:2017-08-09 08:27:59
【问题描述】:

我正在尝试使用 react-router 4.0.0 设置一个通用的反应应用程序。

除了我的链接标签在服务器和客户端上的呈现方式不同之外,服务器端呈现工作正常。这是错误消息:

警告:React 尝试在容器中重用标记,但校验和无效。这通常意味着您正在使用服务器渲染,并且在服务器上生成的标记不是客户端所期望的。 React 注入了新的标记来补偿哪些工作,但是您已经失去了服务器渲染的许多好处。相反,请弄清楚为什么在客户端或服务器上生成的标记不同:

(client) o Furb</h1><a href="./" data-reactid="4"
(server) o Furb</h1><a href="/./" data-reactid="4

我对 react-router 和一般反应非常陌生,所以请记住,这可能是我的代码中的一个微不足道的错误。另外,我正在学习,所以,我的代码中可能还有其他吵闹的错误,提前抱歉。

在网上查找我想出了一个包含类似问题的错误修复:https://github.com/ReactTraining/react-router/pull/4484

但是,这个补丁包含在 react-router 4.0.0 中(我戳了一下代码,它确实已修复)。因此,我的问题不是由这个引起的。

经过大量修改后,我怀疑我的配置或由于我对自己在做什么的有限理解而导致的错误。例如,对于StaticRouter,我使用location={req.originalUrl} 而不是location={req.url},因为req.url 似乎总是/,我不知道为什么。

我在下面发布了我认为相关的文件,但如果您想查看完整的代码,您可以在这里找到:https://github.com/magp/furb/tree/universal

package.json

{
  "name": "furb",
  "version": "0.0.1",
  "description": "A boilerplate for Firebase-UniversalRedux-Bootstrap/MaterialUI projects",
  "main": "app/server.jsx",
  "scripts": {
    "start": "concurrently --kill-others \"npm run start:api\" \"npm run start:back\"",
    "start:back": "node app/serverlauncher.js",
    "start:api": "node api/server.js",
    "clean": "rimraf static",
    "serve:prod": "http-server ./static -o -p 3032",
    "build:app": "NODE_ENV=production webpack --config config/webpack-prod-config.js",
    "build": "npm run clean && npm run build:app && npm run serve:prod",
    "test": "echo 'NODE_ENV=production mocha './tests/**/*.spec.js' --compilers js:babel-core/register'",
    "lint": "eslint --config=./.eslintrc app/**/**/*.jsx"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/magp/furb.git"
  },
  "keywords": [
    "Boilerplate",
    "React",
    "Redux",
    "UniversalJS",
    "Bootstrap",
    "MaterialUI"
  ],
  "author": "magp",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/magp/furb/issues"
  },
  "homepage": "https://github.com/magp/furb#readme",
  "dependencies": {
    "express": "^4.15.2",
    "history": "^4.6.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-hot-loader": "^3.0.0-beta.6",
    "react-router-dom": "^4.0.0"
  },
  "devDependencies": {
    "babel-core": "^6.24.0",
    "babel-loader": "^6.4.0",
    "babel-preset-es2015": "^6.24.0",
    "babel-preset-react": "^6.23.0",
    "concurrently": "^3.4.0",
    "eslint": "^3.17.1",
    "eslint-config-airbnb": "^14.1.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^4.0.0",
    "eslint-plugin-react": "^6.10.0",
    "html-webpack-plugin": "^2.28.0",
    "http-server": "^0.9.0",
    "node-sass": "^4.5.0",
    "rimraf": "^2.6.1",
    "sass-loader": "^6.0.3",
    "style-loader": "^0.14.0",
    "webpack": "^2.2.1",
    "webpack-dev-middleware": "^1.10.1",
    "webpack-hot-middleware": "^2.17.1"
  }
}

app/serverlauncher.js

require('babel-register')({
  presets: [ 'es2015', 'react' ]
});

var app = require('./server.jsx');

app/server.jsx

var path = require('path');
var express = require('express');

var React = require('react');
var ReactDOMServer = require('react-dom/server');
var StaticRouter = require('react-router-dom/StaticRouter').default;
var webpack = require('webpack');

var config = require('../config/webpack-dev-config');
var Routes = require('./routes/Routes.jsx').default;

var app = express();
var compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));

const routes = [
    '/',
    '/about'
];

app.use('*', function (req, res, next) {
  const context = {};
  const componentHTML = ReactDOMServer.renderToString(<StaticRouter context={context} location={req.originalUrl}><Routes /></StaticRouter>);

  const HTML = `
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Static</title>
      </head>
      <body>
        <div id="app">${componentHTML}</div>
        <script type="text/javascript" src="/static/source.js"></script>
      </body>
    </html>
  `;
  res.end(HTML);
});

const PORT = process.env.PORT || 3030;

app.listen(PORT, 'localhost', function(err) {
  if (err) {
    console.log(err);
    return;
  }
  console.log('Listening at http://localhost:3030');
});

app/routes/Routes.jsx

import React from 'react';
import { Route, Switch } from 'react-router-dom';

import List from '../components/List';
import About from '../components/About';
import NotFound from '../components/NotFound';

import links from '../../api/data/links.json';

const linksarr = Object.keys(links).map(function(k) { return links[k] });

function Routes() {
  return (
    <Switch>
      <Route exact path="/" render={props => (<List links={linksarr} {...props} />)} />
      <Route exact path="/about" component={About} />
      <Route component={NotFound} />
    </Switch>
  );
}

export default Routes;

app/components/Layout.jsx

import React from 'react';
import { Link } from 'react-router-dom';

function Layout() {
  return (
    <div>
      <h1>Welcome to Furb</h1>
      <Link to="./">Home</Link>
      <Link to="./about">About</Link>
      <Link to="./test">Test</Link>
    </div>
  );
}

export default Layout;

请原谅这个冗长的问题,并提前感谢您提供的任何帮助。

【问题讨论】:

  • 尝试在链接的“to”字段中删除句点。它应该只是“/”、“/about”等,而不是“./about”。路由不是文件路径,它们是由路由器解析和解释的,而句点会混淆它。

标签: javascript reactjs express react-router react-router-v4


【解决方案1】:

尝试在链接的“收件人”字段中删除句点。它应该只是“/”、“/about”等,而不是“./about”。路由不是文件路径,它们是由路由器解析和解释的,而句点会混淆它。

import React from 'react';
import { Link } from 'react-router-dom';

function Layout() {
  return (
    <div>
      <h1>Welcome to Furb</h1>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
      <Link to="/test">Test</Link>
    </div>
  );
}

export default Layout;

【讨论】:

  • 感谢您的快速答复!你是绝对正确的。这解决了问题!
猜你喜欢
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 2019-10-31
  • 2020-04-28
  • 2021-03-07
  • 2016-06-07
  • 2018-05-03
相关资源
最近更新 更多