node.js - 手动刷新或写入时,React 路由器 URL 不起作用。并获取 html 数据而不是 JSON 数据
问题描述
我正在使用 React-router 的 MERN 网站上工作,当我单击链接按钮时它工作正常,但是当我刷新我的网页时,它不会加载我想要的内容。手动刷新或写入时,React 路由器 URL 不起作用。所以我看到了很多解决这个问题的方法。我使用了一种解决方案,即捕获 server.js 中的每个 get 请求并发送 index.html 文件。
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client", "build")));
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
}
这个过程完美运行并解决了 react-router 问题,但在客户端,我通过发送 Axios 获取请求来获取一些数据。
useEffect(() => {
axios
.get("/posts")
.then((result) => {
console.log(result.data);
//result.data contains index.html file instead of json data
})
.catch((error) => {
console.log(error);
});
}, []);
该获取请求的响应应该具有获取 JSON 数据但它获取 index.html 文件。我知道它会获取那个 index.html 文件,因为我在捕获 server.js 中的所有请求时发送了 index.html 文件。
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
但是如果我删除那行代码,那么我在手动刷新或写入 URL 时会遇到 React router URL doesn't work 错误。我想要的是解决 react-router 问题,并从该请求中获取 JSON 数据,并使用该数据映射这些数据。这是我的 server.js、App.js 和 Posts.js 代码
服务器.js
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
require("dotenv").config();
const path = require("path");
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client", "build")));
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
}
mongoose
.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
})
.then(() => {
console.log("Database connected");
})
.catch((err) => {
console.log(`Database error ${err.message}`);
});
const postsSchema = new mongoose.Schema({
title: {
type: String,
},
description: {
type: String,
},
});
const Posts = new mongoose.model("Posts", postsSchema);
app.get("/posts", (req, res) => {
Posts.find({}, (error, post) => {
if (error) {
res.json(error.message);
} else {
res.json(post);
}
});
});
app.listen(process.env.PORT || 5000, () => {
console.log("App started in port 5000");
});
应用程序.js
import "./App.css";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Posts from "./Posts";
import Header from "./Header";
function App() {
return (
<div className="App">
<Router>
<Header />
<Switch>
<Route exact path="/posts" component={Posts} />
</Switch>
</Router>
</div>
);
}
export default App;
Posts.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
function Posts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
axios
.get("/posts")
.then((result) => {
setPosts(result.data);
console.log(result.data);
//result.data contains index.html file instead of JSON data
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<div className="container mt-5">
<div className="row">
{posts.map((post) => {
return (
<div className="col-sm-3" key={post._id}>
<h6>{post.title}</h6>
<p>{post.description}</p>
<Link className="nav-link active" to={`/post/${post._id}`}>
Read More
</Link>
</div>
);
})}
</div>
</div>
);
}
export default Posts;
如果您知道我的代码有什么问题,请帮助我。以及如何获取 JSON 数据而不是 index.html 文件
解决方案
const express = require("express");
//const bodyParser = require("body-parser"); not necessary
const mongoose = require("mongoose");
require("dotenv").config();
const path = require("path");
const app = express();
//app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: false }));
//app.use(bodyParser.json());
app.use(express.json());
/*if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client", "build")));
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
}*/
mongoose
.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
})
.then(() => {
console.log("Database connected");
})
.catch((err) => {
console.log(`Database error ${err.message}`);
});
const postsSchema = new mongoose.Schema({
title: {
type: String,
},
description: {
type: String,
},
});
const Posts = new mongoose.model("Posts", postsSchema);
// Static Files Folder
app.use(express.static(path.join(__dirname,"client","bluild")))
// Routes
app.use("/posts", (req, res)=>{
Posts.find({}, (error, post) => {
if (error) {
res.json(error.message);
} else {
res.json(post);
}
});
})
app.use("/*", (req, res)=>{res.sendFile(path.join(__dirname,"public/index.html"))}) /*always at the end*/
app.listen(process.env.PORT || 5000, () => {
console.log("App started in port 5000");
});
这应该可行,现在我想给你一些提示。
- 最新版本中的 Express 包括 body-parser 如果您要使用 1 个服务器来处理客户端 + 服务器端(我的意思是不使用 create-react-app 并创建其他服务器来发出请求):
- 拳头,您必须清除静态文件夹,您将在其中放置使用 react 制作的捆绑包(在您的情况下,我认为它是 index.js)。
- 没有必要为不存在的路由重新发送捆绑包,您可以将 json 发送到客户端 (res.json({Status: 'NotFound'})) 并且您必须在那里展示用户该页面不存在(使用反应,创建一个组件 NotFound 并确保它是路由中的最后一个路由)或只是发送 res.status(401)。但是,如果您使用下一点,这不是必需的。
- 在 react-router 中,你应该使用“HashRouter 作为路由器”而不是“BrowserRouter 作为路由器”,解释起来有点困难,你可以找到它。
推荐阅读
- css - CSS - 咆哮时网格失去结构
- sql-server - 如何从我的结果中删除 CASE 语句?
- javascript - 如何通过“@solana/web3.js”和“@solana/spl-token”调用 nft 程序?
- javascript - 如何在 Javascript 中访问以下对象参数
- symfony - 更改来自供应商捆绑包的订阅者的优先级
- swift - 如何在 Swift 中将纹理应用于 3d obj 模型上的特定通道?
- vue.js - VueJS 3 - 如何使用可拖动的嵌套元素但防止重复项
- java - 如何在 JUnit 测试中管理 JNDI 上下文?
- c# - 具有多个模型的 RestPost
- php - cakephp 4 中的 I18n::setLocale('en_FR') 是否正确?