React路由渲染DishDetail报Functions are not valid as a React child错误
问题修复方案
你遇到的报错和路由参数传递问题均为React Router v6版本用法不匹配导致,按以下步骤修改即可:
1. 修复"Functions are not valid as a React child"报错
报错的直接原因是/home路由的element属性写法错误:你当前写的是element={HomePage()},这是直接执行函数拿到返回值,绕过了React的组件渲染机制,一旦渲染链路中出现函数类型的返回值就会触发该警告。
- 修正方式:和其他路由保持一致,将函数组件以JSX标签形式传入,改为
element={<HomePage />}
2. 修复路由参数无法获取的问题
你当前用的是React Router v5版本的match.params获取参数的写法,但v6版本已经移除了路由组件自带的match/history/location props,所有路由参数必须通过useParams钩子获取。注意useParams是React钩子,只能在函数组件内调用,正好可以用在你写的DishWithId组件里:
- 去掉
DishWithId里对match的props解构,直接在组件内调用useParams拿到dishId - 不要把
DishWithId定义在Main类组件的render方法里,否则每次render都会生成新的组件引用,导致路由组件反复重挂载丢状态,把它移到Main类外部即可 - 路由渲染
DishWithId时,把redux中拿到的dishes、comments作为props传入即可
修正后的DishWithId代码:
// 写在Main类外部 import { useParams } from 'react-router-dom'; const DishWithId = ({dishes, comments}) => { const { dishId } = useParams(); const targetId = parseInt(dishId, 10); return( <DishDetail dish={dishes.filter((dish) => dish.id === targetId)[0]} comments={comments.filter((comment) => comment.dishId === targetId)} /> ); };
修正后的Routes配置代码:
<Routes> <Route path="/home" element={<HomePage />} /> <Route exact path="/menu" element={<Menu dishes={this.props.dishes} />} /> {/* 传入需要的redux数据 */} <Route path='/menu/:dishId' element={<DishWithId dishes={this.props.dishes} comments={this.props.comments} />} /> <Route exact path="/contactus" element={<Contact />} /> <Route exact path="/aboutus" element={<About leaders={this.props.leaders}/>} /> <Route path="*" element={<Navigate replace to="/home" />} /> </Routes>
3. 额外的边界问题修复
你的RenderComments组件没有做空值兜底,如果某道菜没有对应评论,comments为undefined时调用map方法会直接报错,加个兜底即可:
function RenderComments({comments}) { // comments为空时用空数组兜底 const commentList = (comments || []).map((comment)=> { return ( <div key={comment.id} className="col-12 col-md-5 m-1"> <p>{comment.comment}</p> <p>--{comment.author} , {new Intl.DateTimeFormat('en-US', {year: 'numeric', month: 'long', day: '2-digit' }).format(new Date(comment.date))}</p> </div> ) }); return( <div className="col-12 col-md-5 m-1"> <h4>Comments</h4> {commentList} </div> ); }
注意事项
- Route的
element属性必须传入React元素(即<Component />形式),不要直接调用函数组件传返回值 - React Router v6中所有路由相关值都要通过对应钩子获取,如果要在class组件中使用,需要写高阶组件包装后把钩子返回值作为props传入
- 不要在render方法内定义新的React组件,避免不必要的重挂载
内容的提问来源于stack exchange,提问作者Ivan Lau
相关产品推荐
相关产品推荐

