React路由跳转后BookDetail子组件接收bookId prop为undefined问题排查
问题原因
- 核心问题是你使用
window.location.href进行路由跳转,该操作会触发浏览器整页刷新,React应用的状态selectedBook保存在运行内存中,页面刷新后整个应用重新初始化,selectedBook会回到初始的undefined值,所以跳转到详情页后传递的prop自然为空。 - Main组件中的
useEffect未添加空依赖数组,会导致每次组件渲染都重复触发axios请求,存在性能问题。 setBooks(books = res.data)写法不规范,useState返回的更新函数直接传入新值即可,不需要额外赋值操作。selectedBook未设置初始值,首次渲染时默认就是undefined。
修复方案
1. 替换路由跳转方式
不要用原生的页面跳转,改用React Router提供的编程式导航避免整页刷新,你当前使用的是v5版本的react-router-dom(存在Switch组件),使用useHistory实现跳转:
修改Books.js代码:
import React from 'react' import { useHistory } from 'react-router-dom' // 新增导入 const Books = ({books, onBookSelect}) => { const history = useHistory() // 初始化history实例 const sendBookId = e => { let bookId = e.target.value onBookSelect(bookId) // 把这里的测试字符串改成实际取到的bookId history.push('/details') // 替换原来的setTimeout和window.location跳转逻辑 } return ( <div> <div className='books'> {books.map(book => ( <div className='book' key={book.id}> {/* 给循环项加唯一key值,避免React警告 */} <h2>{book.name}</h2> <p>Author: <a href='#'>{book.author}</a></p> <button className="btn" value={book.id} onClick={sendBookId}>View Details</button> </div> ))} </div> </div> ) } export default Books
2. 修正Main组件的写法
修改Main.js中的useEffect和状态更新逻辑:
// 给selectedBook设置初始值为null let [selectedBook, setSelectedBook] = useState(null) let [books, setBooks] = useState([]) // 给useEffect加空依赖数组,只在首次挂载时执行请求 useEffect(() => { axios.get('http://127.0.0.1:8000/api/get-books') .then(res => { setBooks(res.data) // 直接传入新值即可 }) }, [])
可选优化:兼容页面刷新场景
如果需要用户刷新详情页后仍能拿到bookId,可以将bookId放到路由参数中:
首先修改Main.js的路由配置:
<Route path={`/details/:bookId`}> <BookDetail /> </Route>
跳转时携带参数:
// Books.js中的跳转逻辑修改 history.push(`/details/${bookId}`)
在BookDetail中从路由参数取id:
import { useParams } from 'react-router-dom' const BookDetail = () => { const { bookId } = useParams() return ( <div> <p>book: {bookId}</p> </div> ) }
内容的提问来源于stack exchange,提问作者Lun
相关产品推荐
相关产品推荐

