乐趣区

关于react.js:react18中使用reactrouterdom-v6浏览器前进后退没有正确选中菜单的解决办法

事件起因就是发现在浏览器点击后退后退的时候,menu 的选中状态并不会自动更新,如下图所示:

想要的正确成果如下:

那话不多说,开始思考解决办法


应用的 ui 库是 antd 的,旁边的 menu 即 Menu,查阅官网相干组件材料可知,须要在 menu 组件上加上 selectedKeys 属性

本地的 menu 局部代码如下

<Menu
  theme="dark"
  mode="inline"
  defaultSelectedKeys={[defaultSelectedKeys]}
  onClick={onClick}
  items={[
    {
      key: '/todolist',
      icon: <UserOutlined />,
      label: 'todolist',
    },
    {
      key: '/form',
      icon: <VideoCameraOutlined />,
      label: 'Form',
    },
    {
      key: '/test',
      icon: <UploadOutlined />,
      label: '各种测试',
    },
  ]}
 />

defaultSelectedKeys 换成selectedKeys={[selectedKeys]}

<Menu
  ...
  selectedKeys={[selectedKeys]}
 />

之所以这么做,是因为在加上了 selectedKeys 当前,实际上 defaultSelectedKeys 曾经齐全被前者代替了,后者要不要都不影响页面体现。

然而,很重要的一点就是换成了 selectedKeys 当前,须要手动在点击事件中更改其对应的值,不然选中的项永远不会扭转,如下图所示

另外,记得给 selectedKeys 加上初始值,不然页面第一次进来的时候是没有选中项的


替换完后,接下来就是须要获取当前页面上的 url 地址了,因为 selectedKeys 是依据 Menuitemskey 来进行准确匹配的。

引入如下代码

import {useLocation} from 'react-router-dom'

const location = useLocation();

useEffect(()=>{window.onpopstate = function (e: PopStateEvent) {console.log('location',location)
  };
  return (()=>{window.onpopstate = null;})
},[])

useLocationreact-router-dom 自带的办法,返回以后路由的相干信息如下:

window.onpopstate为浏览器点击后退后退的时候触发的办法,传递的参数不必管,在这里也用不上。

即,当初具体思路为:
在浏览器点击后退后退的时候,拿到以后浏览器的 url,返回给 selectedKeys 从而使 menu 组件可能失常选中对应的菜单项

然而,问题呈现了

在控制台打印console.log(location,location.pathname)

能够看到,打印进去的 pathname 的值只会是第一个路由的值,再也不会变了,这就很奇怪了啊,明明 url 都变了,为什么这个值不会变了呢?

然而,当把 pathname 的值打印到页面上的时候,状况产生了变动

能够看到,页面上的pathname 是显示正确的,和 url 保持一致!

这阐明在事件中的 pathname 值固定为赋值时候的值,不会自动更新,而页面跳转时候的 pathname 会放弃更新!

解决办法:应用 useRefpathname的值进行跟踪更新, 代码如下

import {useRef} from 'react';

const locationRef = useRef(location);
locationRef.current = location;

useEffect(()=>{window.onpopstate = function (e: PopStateEvent) {console.log('location',location.pathname,'locationRef.current',locationRef.current.pathname)
  };
  return (()=>{window.onpopstate = null;})
},[])

能够看到,应用useRef 打印进去的值是正确的

所以在 useEffect 中,加上赋值语句,所须要的成果就实现啦

useEffect(()=>{window.onpopstate = function (e: PopStateEvent) {setSelectedKeys(locationRef.current.pathname); 
    console.log('location',location.pathname,'locationRef.current',locationRef.current.pathname)
  };
  return (()=>{window.onpopstate = null;})
},[])

退出移动版