React Router从对象列表跳转至单对象详情页的最佳实践是什么
实现步骤
1. 改造Users组件添加跳转逻辑
推荐使用react-router-dom提供的Link组件实现跳转,语义更友好,也支持浏览器原生的新标签页打开等操作:
// Users.js import { Link } from "react-router-dom"; const users = [ { id: 1, name: "Tom" }, { id: 2, name: "Ken" } ]; export default function Users() { return ( <div className="App"> <h1>用户列表</h1> {users.map((user) => { return ( <div key={user.id}> <Link to={`/user/${user.id}`}> <button>{user.name}</button> </Link> </div> ); })} </div> ); }
如果跳转前需要执行额外的校验逻辑,也可以用useHistory实现:
// Users.js import { useHistory } from "react-router-dom"; const users = [ { id: 1, name: "Tom" }, { id: 2, name: "Ken" } ]; export default function Users() { const history = useHistory(); const goToProfile = (userId) => { // 此处可添加跳转前的校验逻辑 history.push(`/user/${userId}`); // 如果需要临时传递用户信息避免二次请求,可携带state参数: // history.push(`/user/${userId}`, { user }); }; return ( <div className="App"> <h1>用户列表</h1> {users.map((user) => { return ( <div key={user.id}> <button onClick={() => goToProfile(user.id)}>{user.name}</button> </div> ); })} </div> ); }
2. UserProfile组件获取路由参数
使用react-router-dom提供的useParams钩子即可直接拿到路由中的id参数:
// UserProfile.jsx import { useParams, useHistory } from "react-router-dom"; export default function UserProfile() { // 解构获取路由中定义的id参数 const { id } = useParams(); const history = useHistory(); // 可选:如果跳转时携带了state参数,可以用useLocation获取 // const location = useLocation(); // const user = location.state?.user; // 参数合法性校验 const userId = Number(id); if (isNaN(userId) || userId < 1) { // 非法参数直接跳回用户列表或404页 history.replace('/user'); return null; } // 如果用户数据来自后端,可通过useEffect触发请求 // const [user, setUser] = useState(null); // const [loading, setLoading] = useState(true); // useEffect(() => { // setLoading(true); // fetchUser(userId).then(res => { // setUser(res.data); // }).catch(err => { // // 错误处理,比如用户不存在跳转404 // history.replace('/404'); // }).finally(() => setLoading(false)); // }, [userId]) // 如果是前端静态存储的用户数据,直接匹配即可 // const user = users.find(item => item.id === userId); // if (!user) { // history.replace('/user'); // return null; // } return ( <div className="App"> <h1>用户资料</h1> <p>我是用户{userId}</p> {/* 拿到完整user对象后即可展示全量用户信息 */} {/* <p>用户名:{user.name}</p> */} </div> ); }
单用户页面开发最佳实践
- 优先做参数校验:拿到路由id后第一时间做格式、范围校验,非法参数直接跳转兜底页面,避免后续逻辑出错
- 数据逻辑封装:用户数据如果来自后端,建议把数据请求、loading、错误处理逻辑封装成自定义Hook,复用性更高
- 慎用路由state传参:state内的数据刷新页面就会丢失,仅适合传递临时状态(比如列表页的筛选条件,方便返回时恢复状态),核心用户数据一定要通过id重新请求获取
- 增加权限拦截:如果用户资料页需要登录权限,可以配合路由守卫做拦截,未登录用户直接跳转登录页
- 可访问性优化:跳转优先用Link组件而非纯JS触发跳转,有利于屏幕阅读器识别,也支持浏览器右键打开新标签页的操作
内容的提问来源于stack exchange,提问作者CCCC
相关产品推荐
相关产品推荐

