刷新后无法呈现 React 页面,而是显示原始数据
Unable to render React page after refresh, instead showing raw data
各位!我正在尝试使用 Node/React/Mongoose 构建一个没有 CRA 命令的应用程序,该命令还包括自定义 webpack。
我设法在单个 React 页面中构建所有内容 (App.jsx),但代码看起来很乱。我设法通过首先从数据库中获取数据来构建它,然后围绕它构建所有内容。现在可行了,但我想更进一步。无论获取的数据如何,我都想构建一个应用程序。
现在,我发现自己遇到的问题最好用幻灯片显示。我该如何解决这个问题?我试过更改路径,但没有成功。
进入主页后,正在呈现导航栏。我也可以刷新,它不会坏。
当我使用导航栏导航到 /teacher 时,它会很好地加载所有内容。
但是当我刷新或手动输入 url localhost8080/teacher 时,问题就出现了。它不是组件,而是获取原始数据。
这是我与问题相关的代码:
server.js
app.use('/teacher', authRoutes);
app.use('/class', classRoutes);
app.get('/', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
routes.js
router.get('/signup', authController.teacherList);
控制器
exports.teacherList = (req, res, next) => {
Teacher.find()
.then(teacher => {
return res.send(teacher)
})
.catch(err => console.log(err));
}
App.jsx
import React, { Component } from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import TeacherComponent from './Teacher'
import ClassComponent from './Class'
export default class App extends Component {
render() {
return (
<Router>
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<ul className="navbar-nav mr-auto">
<li><Link to={'/class'} className="nav-link">Class</Link></li>
<li><Link to={'/teacher'} className="nav-link">Teacher</Link></li>
</ul>
</nav>
<hr />
<Routes>
<Route path='/class' element={<ClassComponent />} />
<Route path='/teacher' element={<TeacherComponent />} />
</Routes>
</div>
</Router>
);
}
}
Teacher.jsx
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom'
import Select from 'react-select';
import 'bootstrap/dist/css/bootstrap.min.css';
class Teacher extends Component {
constructor(props) {
super(props);
this.state = {
teachers: [],
isSignedUp: false,
firstName : '',
lastName: '',
email: '',
password: '',
studentsClass: {
students: []
}
};
}
componentDidMount() {
fetch('http://localhost:8080/teacher')
.then(response => response.json())
.then(teachers => this.setState({teachers: teachers}));
}
handleFirstName = (e) => {
this.setState({firstName: e.target.value});
}
handleLastName = (e) => {
this.setState({lastName: e.target.value});
}
handleEmail = (e) => {
this.setState({email: e.target.value});
}
handlePassword = (e) => {
this.setState({password: e.target.value});
}
signUp = () => {
const requestOptions = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({firstName: this.state.firstName , lastName: this.state.lastName, email: this.state.email , password: this.state.password}),
};
fetch("/teacher/signup", requestOptions)
.then((response) => {
return response.json();
})
.then(() => {
fetch('http://localhost:8080/class')
.then(response => response.json())
.then(teachers => this.setState({teachers: teachers}));
})
.catch((err) => {
console.log(err)
})
}
render() {
// const teachers = this.state.teachers.map(teacher => <div key={teacher._id}>{teacher.firstName} - {teacher.lastName}</div>);
const teachers = []
for (let i = 0; i < this.state.teachers.length; i++) {
teachers.push({label: this.state.teachers[i].firstName + ' ' + this.state.teachers[i].lastName})
}
return (
<div>
<div className="container">
<div className="row" style={{marginTop: "100px"}}>
<div className="col-md-4"></div>
<div className="col-md-4">
<Select placeholder="Select teacher"options={ teachers } />
</div>
<div className="col-md-4"></div>
</div>
</div>
<div></div>
<div style={{display: "flex", alignItems: "center", justifyContent: "center", marginTop: "100px"}}><h5>Signup:</h5></div>
<div style={{margin: "20px auto", borderTop: "2px solid black", width: "400px", textAlign: "center"}}>
<form style={{marginTop: "30px"}} onSubmit={(event) => {
event.preventDefault()
this.signUp(this.state.teacher)
}} >
<input style={{textAlign: "center"}} type="text" name="firstName" placeholder="First Name" value={this.state.firstName} onChange={this.handleFirstName} />
<div></div>
<br></br>
<input style={{textAlign: "center"}} type="text" name="lastName" placeholder="Last Name" value={this.state.lastName} onChange={this.handleLastName}/>
<div></div>
<br></br>
<input style={{textAlign: "center"}} type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmail}/>
<div></div>
<br></br>
<input style={{textAlign: "center"}} type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePassword}/>
<div></div>
<br></br>
<input className="button button2" type="submit" />
</form>
</div>
</div>
);
}
}
export default Teacher;
以及代理请求的 webpack:
const webpack = require("webpack");
const path = require("path");
module.exports = {
entry: path.resolve(__dirname, "./src/index.js"),
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: ["file-loader"]
}
],
},
resolve: {
extensions: ["*", ".js", ".jsx"],
},
mode: process.env.NODE_ENV,
output: {
path: path.resolve(__dirname, "./docs"),
filename: "bundle.js",
},
// [webpack-dev-server] "hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.
plugins: [new webpack.HotModuleReplacementPlugin()],
devServer: {
// contentBase is deprecated by static in webpack v5
proxy: {
'/': 'http://localhost:3000/',
},
// contentBase: path.resolve(__dirname, "./docs"),
hot: true,
},
};
问题在于您如何配置 server.js 文件
app.use('/teacher', authRoutes);
app.use('/class', classRoutes);
app.get('/', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
现在假设您正在向服务器发送请求以获取 url /teacher
中的数据,现在它正在完美地完成工作。因为,它会遇到第一行并向您发送原始 json 并完成它。
一个解决方案是将所有 api 模块保留在“/api”附加路径中。因此,它们不会与您的常规路由冲突。
app.use('/api/teacher', authRoutes);
app.use('/api/class', classRoutes);
app.get('/', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
这应该可以解决您的问题。
编辑:
最后一条路线应该总是 return 主页。所以,path-matching
需要一颗星
app.get('/*', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
你的服务器是 运行 在本地主机 8080 上,所以客户端可能是 运行 在本地主机上 3030 之类的东西请检查一下,因为我看到你正在调用服务器 api 8080.
你可以这样优化你的代码 -
<Route path='/class' element={()=><ClassComponent teacher={this.state.teachers} />} />
<Route path='/teacher' element={()=><TeacherComponent teacher={this.state.teachers/>} />
试试这个,请同时上传 ClassComponent 和 TeacherComponent。
各位!我正在尝试使用 Node/React/Mongoose 构建一个没有 CRA 命令的应用程序,该命令还包括自定义 webpack。
我设法在单个 React 页面中构建所有内容 (App.jsx),但代码看起来很乱。我设法通过首先从数据库中获取数据来构建它,然后围绕它构建所有内容。现在可行了,但我想更进一步。无论获取的数据如何,我都想构建一个应用程序。
现在,我发现自己遇到的问题最好用幻灯片显示。我该如何解决这个问题?我试过更改路径,但没有成功。
进入主页后,正在呈现导航栏。我也可以刷新,它不会坏。
当我使用导航栏导航到 /teacher 时,它会很好地加载所有内容。
但是当我刷新或手动输入 url localhost8080/teacher 时,问题就出现了。它不是组件,而是获取原始数据。
这是我与问题相关的代码:
server.js
app.use('/teacher', authRoutes);
app.use('/class', classRoutes);
app.get('/', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
routes.js
router.get('/signup', authController.teacherList);
控制器
exports.teacherList = (req, res, next) => {
Teacher.find()
.then(teacher => {
return res.send(teacher)
})
.catch(err => console.log(err));
}
App.jsx
import React, { Component } from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import TeacherComponent from './Teacher'
import ClassComponent from './Class'
export default class App extends Component {
render() {
return (
<Router>
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<ul className="navbar-nav mr-auto">
<li><Link to={'/class'} className="nav-link">Class</Link></li>
<li><Link to={'/teacher'} className="nav-link">Teacher</Link></li>
</ul>
</nav>
<hr />
<Routes>
<Route path='/class' element={<ClassComponent />} />
<Route path='/teacher' element={<TeacherComponent />} />
</Routes>
</div>
</Router>
);
}
}
Teacher.jsx
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom'
import Select from 'react-select';
import 'bootstrap/dist/css/bootstrap.min.css';
class Teacher extends Component {
constructor(props) {
super(props);
this.state = {
teachers: [],
isSignedUp: false,
firstName : '',
lastName: '',
email: '',
password: '',
studentsClass: {
students: []
}
};
}
componentDidMount() {
fetch('http://localhost:8080/teacher')
.then(response => response.json())
.then(teachers => this.setState({teachers: teachers}));
}
handleFirstName = (e) => {
this.setState({firstName: e.target.value});
}
handleLastName = (e) => {
this.setState({lastName: e.target.value});
}
handleEmail = (e) => {
this.setState({email: e.target.value});
}
handlePassword = (e) => {
this.setState({password: e.target.value});
}
signUp = () => {
const requestOptions = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({firstName: this.state.firstName , lastName: this.state.lastName, email: this.state.email , password: this.state.password}),
};
fetch("/teacher/signup", requestOptions)
.then((response) => {
return response.json();
})
.then(() => {
fetch('http://localhost:8080/class')
.then(response => response.json())
.then(teachers => this.setState({teachers: teachers}));
})
.catch((err) => {
console.log(err)
})
}
render() {
// const teachers = this.state.teachers.map(teacher => <div key={teacher._id}>{teacher.firstName} - {teacher.lastName}</div>);
const teachers = []
for (let i = 0; i < this.state.teachers.length; i++) {
teachers.push({label: this.state.teachers[i].firstName + ' ' + this.state.teachers[i].lastName})
}
return (
<div>
<div className="container">
<div className="row" style={{marginTop: "100px"}}>
<div className="col-md-4"></div>
<div className="col-md-4">
<Select placeholder="Select teacher"options={ teachers } />
</div>
<div className="col-md-4"></div>
</div>
</div>
<div></div>
<div style={{display: "flex", alignItems: "center", justifyContent: "center", marginTop: "100px"}}><h5>Signup:</h5></div>
<div style={{margin: "20px auto", borderTop: "2px solid black", width: "400px", textAlign: "center"}}>
<form style={{marginTop: "30px"}} onSubmit={(event) => {
event.preventDefault()
this.signUp(this.state.teacher)
}} >
<input style={{textAlign: "center"}} type="text" name="firstName" placeholder="First Name" value={this.state.firstName} onChange={this.handleFirstName} />
<div></div>
<br></br>
<input style={{textAlign: "center"}} type="text" name="lastName" placeholder="Last Name" value={this.state.lastName} onChange={this.handleLastName}/>
<div></div>
<br></br>
<input style={{textAlign: "center"}} type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmail}/>
<div></div>
<br></br>
<input style={{textAlign: "center"}} type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePassword}/>
<div></div>
<br></br>
<input className="button button2" type="submit" />
</form>
</div>
</div>
);
}
}
export default Teacher;
以及代理请求的 webpack:
const webpack = require("webpack");
const path = require("path");
module.exports = {
entry: path.resolve(__dirname, "./src/index.js"),
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: ["file-loader"]
}
],
},
resolve: {
extensions: ["*", ".js", ".jsx"],
},
mode: process.env.NODE_ENV,
output: {
path: path.resolve(__dirname, "./docs"),
filename: "bundle.js",
},
// [webpack-dev-server] "hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.
plugins: [new webpack.HotModuleReplacementPlugin()],
devServer: {
// contentBase is deprecated by static in webpack v5
proxy: {
'/': 'http://localhost:3000/',
},
// contentBase: path.resolve(__dirname, "./docs"),
hot: true,
},
};
问题在于您如何配置 server.js 文件
app.use('/teacher', authRoutes);
app.use('/class', classRoutes);
app.get('/', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
现在假设您正在向服务器发送请求以获取 url /teacher
中的数据,现在它正在完美地完成工作。因为,它会遇到第一行并向您发送原始 json 并完成它。
一个解决方案是将所有 api 模块保留在“/api”附加路径中。因此,它们不会与您的常规路由冲突。
app.use('/api/teacher', authRoutes);
app.use('/api/class', classRoutes);
app.get('/', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
这应该可以解决您的问题。
编辑: 最后一条路线应该总是 return 主页。所以,path-matching
需要一颗星app.get('/*', (req, res, next) => {
res.sendFile(path.resolve(__dirname, "../docs/index.html"))
})
你的服务器是 运行 在本地主机 8080 上,所以客户端可能是 运行 在本地主机上 3030 之类的东西请检查一下,因为我看到你正在调用服务器 api 8080.
你可以这样优化你的代码 -
<Route path='/class' element={()=><ClassComponent teacher={this.state.teachers} />} />
<Route path='/teacher' element={()=><TeacherComponent teacher={this.state.teachers/>} />
试试这个,请同时上传 ClassComponent 和 TeacherComponent。