如何在React Router中实现路由向组件传值及跨组件数据持久化?
React Router 路由传参 + 跨组件数据持久化实现方案
一、React Router 传参及组件获取方法
React Router给组件传参主要有三种常用方式,对应不同场景:
1. URL路径参数(比如/user/123里的123)
适合传递ID这类需要在URL中显示的标识。路由定义时用:参数名占位,组件里用useParams直接拿:
// 路由配置 <Route path="/user/:userId" element={<UserDetail />} /> // UserDetail组件获取参数 import { useParams } from 'react-router-dom'; function UserDetail() { const { userId } = useParams(); return <div>当前用户ID:{userId}</div>; }
2. 路由状态(state)
适合传递不想暴露在URL里的复杂数据,比如用户对象。跳转时通过navigate的第二个参数传state,组件用useLocation获取:
// 跳转页面的组件 import { useNavigate } from 'react-router-dom'; function UserList() { const navigate = useNavigate(); const jumpToDetail = () => { // 传递用户数据到目标页面 navigate('/user/detail', { state: { userName: '张三', age: 25, tags: ['前端', 'React'] } }); }; return <button onClick={jumpToDetail}>查看用户详情</button>; } // 目标页面组件获取state import { useLocation } from 'react-router-dom'; function UserDetail() { const location = useLocation(); // 加个默认值避免state为空报错 const { userName, age, tags } = location.state || {}; return ( <div> <p>用户名:{userName}</p> <p>年龄:{age}</p> <p>标签:{tags?.join(', ')}</p> </div> ); }
3. URL查询参数(比如/user/detail?name=张三&age=25)
适合传递非敏感、需要在URL中保留的简单参数,用useSearchParams来读取:
// 跳转时带查询参数 navigate('/user/detail?name=张三&age=25'); // 组件中获取参数 import { useSearchParams } from 'react-router-dom'; function UserDetail() { const [searchParams] = useSearchParams(); const userName = searchParams.get('name'); const age = searchParams.get('age'); return ( <div> <p>用户名:{userName}</p> <p>年龄:{age}</p> </div> ); }
二、用React Hooks实现跨组件数据持久化(结合localStorage)
你之前尝试用useEffect存localStorage,其实可以封装成自定义Hook,复用性更高,还能自动同步状态:
1. 写一个自定义Hook useLocalStorage
这个Hook会帮你处理localStorage的读写,以及组件间的状态同步:
import { useState, useEffect } from 'react'; function useLocalStorage(key, initialValue) { // 初始化时先从localStorage读数据,没有就用初始值 const [storedValue, setStoredValue] = useState(() => { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (err) { console.error('读取localStorage出错:', err); return initialValue; } }); // 更新状态时自动同步到localStorage const setValue = (value) => { try { // 支持像useState一样的函数式更新 const valueToStore = typeof value === 'function' ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (err) { console.error('写入localStorage出错:', err); } }; // 监听其他标签页修改localStorage的情况,同步当前组件状态 useEffect(() => { const handleStorageChange = (e) => { if (e.key === key) { setStoredValue(e.newValue ? JSON.parse(e.newValue) : initialValue); } }; window.addEventListener('storage', handleStorageChange); return () => window.removeEventListener('storage', handleStorageChange); }, [key, initialValue]); return [storedValue, setValue]; }
2. 在组件中使用这个Hook
比如在跳转前把数据存到localStorage,目标组件直接读取:
// 列表组件:存储数据并跳转 import { useNavigate } from 'react-router-dom'; import useLocalStorage from './useLocalStorage'; function UserList() { const navigate = useNavigate(); const [currentUser, setCurrentUser] = useLocalStorage('currentUser', null); const goToDetail = () => { const userInfo = { id: 1, name: '张三', age: 25 }; setCurrentUser(userInfo); // 自动存到localStorage navigate('/user/detail'); }; return <button onClick={goToDetail}>查看详情</button>; } // 详情组件:读取持久化数据 import useLocalStorage from './useLocalStorage'; function UserDetail() { const [currentUser] = useLocalStorage('currentUser', null); if (!currentUser) { return <div>暂无用户数据</div>; } return ( <div> <p>用户ID:{currentUser.id}</p> <p>用户名:{currentUser.name}</p> <p>年龄:{currentUser.age}</p> </div> ); }
3. 一些注意点
- localStorage只能存字符串,所以对象要转成JSON再存,读取时要解析回来,上面的Hook已经帮你做了这件事。
- 同标签页内修改localStorage,Hook会通过
setValue自动同步状态;如果是其他标签页修改,会通过storage事件同步。 - 敏感数据别存在localStorage,它是明文存储的,容易被XSS攻击窃取。
内容的提问来源于stack exchange,提问作者Ali Raza
相关产品推荐
相关产品推荐

