React项目部署JBOSS JWS后,用navigate实现表格跳转失效求助
解决方案
核心问题在于你混用了原生DOM操作和React组件体系,同时违反了React Hook的使用规则。以下是正确的实现方案:
1. 修正Hook使用规则
useNavigate必须在函数组件的顶层作用域调用,不能在普通函数(比如loadTableDataNotification)内部调用。在Main组件顶层定义navigate:
function Main() { const navigate = useNavigate(); // 移到组件顶层 // ...其他state和函数 }
2. 放弃原生DOM构建表格,改用React JSX渲染
原生DOM操作(insertRow/insertCell)会脱离React的虚拟DOM管控,导致React Router的导航无法正常工作。改用React状态管理表格数据,通过JSX渲染表格内容。
重构核心思路:
- 用状态存储当前分页的表格结构化数据
- 删除原生DOM操作逻辑,通过React的
map方法渲染表格行 - 用
Link组件或Button+navigate实现跳转
3. 修改后的完整代码
import React, { useEffect, useState } from "react"; import axios from 'axios'; import { Routes, Route, Link, useNavigate } from 'react-router-dom'; import ViewQuery from "./ViewQuery"; import ReactPaginate from "react-paginate"; // 确保已安装该依赖 function Main() { const navigate = useNavigate(); // 正确在组件顶层调用Hook const [currentItems, setCurrentItems] = useState([]); const [pageCount, setPageCount] = useState(0); const [itemOffset, setItemOffset] = useState(0); const itemsPerPage = 10; // 可根据需求调整 // 替换为实际业务变量 const type = ""; const id = ""; const username = ""; useEffect(() => { const urlString = `${window.globalURL}getEagleEyeRequestDataNotification/${type}/${id}`; axios.get(urlString) .then(response => { // 整理成结构化数据,避免字符串拼接 const tableData = response.data.map(item => ({ requestId: item.request_id, description: item.description })); const endOffset = itemOffset + itemsPerPage; setCurrentItems(tableData.slice(itemOffset, endOffset)); setPageCount(Math.ceil(tableData.length / itemsPerPage)); }); }, [itemOffset, itemsPerPage, type, id]); const handlePageClick = (event) => { const newOffset = event.selected * itemsPerPage; setItemOffset(newOffset); }; // 自定义跳转函数,用于Button场景 const goToDetail = (requestId) => { navigate(`/ViewQuery?request_id=${requestId}&id=${id}&name=${username}&type=${type}`); }; return ( <div id='myApp' style={{ margin: "10px" }}> <Routes> <Route path="ViewQuery" element={<ViewQuery />} /> </Routes> <table style={{ padding: 0 }}> <tr> <td style={{ backgroundColor: "#b6e4fe", color: "white", width: "8%" }}></td> <td> <br /> <table style={{ width: '100%', borderTop: '1px solid grey', borderBottom: '1px solid grey', textAlign: 'left', fontFamily: 'Calibri', fontSize: '18px', color: 'grey', fontWeight: 'bold' }}> <tr><td>NOTIFICATION</td></tr> </table> {/* React方式渲染表格 */} <table id="tableNotification" cellspacing="5" cellpadding="5"> <thead> <tr style={{ fontSize: '12px', color: 'grey', fontWeight: 'bold' }}> <td>Req ID</td> <td>Description</td> </tr> </thead> <tbody> {currentItems.map(item => ( <tr key={item.requestId} style={{ fontSize: "12px", color: "grey" }}> {/* 方案1:用Link组件(推荐,符合React Router规范) */} <td> <Link to={`/ViewQuery?request_id=${item.requestId}&id=${id}&name=${username}&type=${type}`} style={{ textDecoration: 'none', color: 'blue' }} > {item.requestId} </Link> </td> {/* 方案2:用Button+navigate(适合需要自定义样式的场景) */} {/* <td> <button onClick={() => goToDetail(item.requestId)} style={{ border: 'none', background: 'none', color: 'blue', cursor: 'pointer', textDecoration: 'underline' }} > {item.requestId} </button> </td> */} <td>{item.description}</td> </tr> ))} </tbody> </table> {/* 分页组件 */} <ReactPaginate nextLabel="next >" onPageChange={handlePageClick} pageRangeDisplayed={3} marginPagesDisplayed={2} pageCount={pageCount} previousLabel="< previous" pageClassName="page-item" pageLinkClassName="page-link" previousClassName="page-item" previousLinkClassName="page-link" nextClassName="page-item" nextLinkClassName="page-link" breakLabel="..." breakClassName="page-item" breakLinkClassName="page-link" containerClassName="pagination" activeClassName="active" renderOnZeroPageCount={null} /> </td> </tr> </table> </div> ); } export default Main;
关键说明
- 原生a标签失效原因:部署到JWS后应用可能存在基路径差异,原生a标签的相对路径无法适配客户端路由,而React Router的
Link会自动处理路由基路径,确保跳转正确。 - Hook规则约束:所有React Hook必须在组件顶层调用,不能在嵌套函数、循环或条件语句中使用,否则会触发无效Hook调用错误。
- innerHTML的限制:innerHTML只能解析普通HTML元素,无法识别React组件(如
Button、Link),必须用JSX方式渲染React组件才能正常工作。
内容的提问来源于stack exchange,提问作者Ezani
相关产品推荐
相关产品推荐

