React中结合useEffect与history.block路由守卫获取最新state数据问题
你遇到的是典型的闭包捕获旧值问题,加上history.block的回调注册时机和路由跳转触发时机存在先后差,导致回调无法拿到最新的status值。以下是两种可直接落地的修改方案:
方案1:用useRef存储最新状态(最通用,兼容所有history版本)
核心思路是用可变的ref对象持有最新的status值,不受闭包限制,改造成本极低:
console.log('in the render', status) // 声明ref存储最新的status const statusRef = useRef(status) // 每次render都更新ref为最新值 statusRef.current = status useEffect(() => { console.log('in the useEffect', status) const unlisten = history.block(route => { // 直接从ref取最新值,不会有闭包旧值问题 console.log('in the block', statusRef.current) return routeGuard({ status: statusRef.current }) }) return unlisten }, []) // 依赖可以留空,不需要每次status变化都重新注册block
方案2:使用react-router官方useBlocker(v6.4+版本适用)
如果你用的是较新版本的react-router,直接用官方封装的useBlocker hook,内部已经处理了状态同步问题:
import { useBlocker } from 'react-router-dom' const blocker = useBlocker( ({ currentLocation, nextLocation }) => { console.log('in the block', status) // 这里直接取status就是最新值,不需要额外处理 return !routeGuard({ status }) } )
内容的提问来源于stack exchange,提问作者Amrit Kahlon
相关产品推荐
相关产品推荐

