React+Node.js界面无法显示求助(已替换Switch/useHistory)
问题描述
我正在使用React和Node.js开发项目,但浏览器中无法显示界面。此前因报错已将Switch替换为Routes,同时把useHistory改为useNavigate,修改App.js后界面就完全无法显示了。我是React和Node.js新手,以下是相关代码:
App.js
import { BrowserRouter as Router, Route, Routes} from "react-router-dom"; import ProductList from "./components/ProductList"; import AddProduct from "./components/AddProduct"; import EditProduct from "./components/EditProduct"; function App() { return ( <Router> <div className="container"> <div className="columns"> <div className="column is-half is-offset-one-quarter"> <Routes> <Route exact path="/"> <ProductList /> </Route> <Route path="/add"> <AddProduct /> </Route> <Route path="/edit/:id"> <EditProduct /> </Route> </Routes> </div> </div> </div> </Router> ); } export default App;
ProductList.js
import { useState, useEffect } from 'react' import axios from "axios"; import { Link } from "react-router-dom"; const ProductList = () => { const [products, setProduct] = useState([]); useEffect(() => { getProducts(); }, []); const getProducts = async () => { const response = await axios.get('http://localhost:5000/products'); setProduct(response.data); } const deleteProduct = async (id) => { await axios.delete(`http://localhost:5000/products/${id}`); getProducts(); } return ( <div> <Link to="/add" className="button is-primary mt-2">Add New</Link> <table className="table is-striped is-fullwidth"> <thead> <tr> <th>No</th> <th>Title</th> <th>Price</th> <th>Actions</th> </tr> </thead> <tbody> { products.map((product, index) => ( <tr key={ product.id }> <td>{ index + 1 }</td> <td>{ product.title }</td> <td>{ product.price }</td> <td> <Link to={`/edit/${product.id}`} className="button is-small is-info">Edit</Link> <button onClick={ () => deleteProduct(product.id) } className="button is-small is-danger">Delete</button> </td> </tr> )) } </tbody> </table> </div> ) } export default ProductList
AddProduct.js
import { useState } from 'react' import axios from "axios"; import { useNavigate } from 'react-router-dom'; const AddProduct = () => { const [title, setTitle] = useState(''); const [price, setPrice] = useState(''); const navigate = useNavigate(); const saveProduct = async (e) => { e.preventDefault(); await axios.post('http://localhost:5000/products',{ title: title, price: price }); navigate.push("/"); } return ( <div> <form onSubmit={ saveProduct }> <div className="field"> <label className="label">Title</label> <input className="input" type="text" placeholder="Title" value={ title } onChange={ (e) => setTitle(e.target.value) } /> </div> <div className="field"> <label className="label">Price</label> <input className="input" type="text" placeholder="Price" value={ price } onChange={ (e) => setPrice(e.target.value) } /> </div> <div className="field"> <button className="button is-primary">Save</button> </div> </form> </div> ) } export default AddProduct
EditProduct.js
/* eslint-disable react-hooks/exhaustive-deps */ import { useState, useEffect } from 'react' import axios from "axios"; import { useNavigate, useParams } from 'react-router-dom'; const EditProduct = () => { const [title, setTitle] = useState(''); const [price, setPrice] = useState(''); const navigate = useNavigate(); const { id } = useParams(); const updateProduct = async (e) => { e.preventDefault(); await axios.patch(`http://localhost:5000/products/${id}`,{ title: title, price: price }); navigate.push("/"); } useEffect(() => { getProductById(); }, []); const getProductById = async () => { const response = await axios.get(`http://localhost:5000/products/${id}`); setTitle(response.data.title); setPrice(response.data.price); } return ( <div> <form onSubmit={ updateProduct }> <div className="field"> <label className="label">Title</label> <input className="input" type="text" placeholder="Title" value={ title } onChange={ (e) => setTitle(e.target.value) } /> </div> <div className="field"> <label className="label">Price</label> <input className="input" type="text" placeholder="Price" value={ price } onChange={ (e) => setPrice(e.target.value) } /> </div> <div className="field"> <button className="button is-primary">Update</button> </div> </form> </div> ) } export default EditProduct
问题排查与修复
1. React Router v6 Route组件语法错误
React Router v6中,Route组件不再支持直接嵌套子组件,必须通过element属性传递要渲染的组件,同时exact属性已被移除(默认精确匹配根路径)。这是导致界面空白的核心原因。
修复后的App.js:
import { BrowserRouter as Router, Route, Routes} from "react-router-dom"; import ProductList from "./components/ProductList"; import AddProduct from "./components/AddProduct"; import EditProduct from "./components/EditProduct"; function App() { return ( <Router> <div className="container"> <div className="columns"> <div className="column is-half is-offset-one-quarter"> <Routes> <Route path="/" element={<ProductList />} /> <Route path="/add" element={<AddProduct />} /> <Route path="/edit/:id" element={<EditProduct />} /> </Routes> </div> </div> </div> </Router> ); } export default App;
2. useNavigate调用方式错误
useNavigate返回的是直接调用的函数,不需要.push()方法,错误的调用会导致报错阻止组件渲染。
修复AddProduct.js中的saveProduct函数:
const saveProduct = async (e) => { e.preventDefault(); await axios.post('http://localhost:5000/products',{ title: title, price: price }); navigate("/"); }
修复EditProduct.js中的updateProduct函数:
const updateProduct = async (e) => { e.preventDefault(); await axios.patch(`http://localhost:5000/products/${id}`,{ title: title, price: price }); navigate("/"); }
3. 额外检查项
- 确认Node.js后端服务正常运行在
http://localhost:5000,可直接在浏览器访问http://localhost:5000/products验证数据是否返回。 - 打开浏览器开发者工具(F12)的Console标签,查看是否有组件导入、跨域请求等其他报错。
完成以上修改后重新启动React项目,界面即可正常显示。
内容的提问来源于stack exchange,提问作者Bart
相关产品推荐
相关产品推荐

