reactjs - document.querySelector() 第一次点击 React Router Link 时总是返回 null 但之后会正确返回
问题描述
我遇到了 React-Router 和 querySelector 的问题。
我有一个Navbar
包含所有CustomLink
导航组件的组件和一个线动画,它监听这些组件并根据当前活动组件显示动画。
// Navbar.tsx
import React, { useCallback, useEffect, useState, useRef } from "react";
import { Link, useLocation } from "react-router-dom";
import CustomLink from "./Link";
const Layout: React.FC = ({ children }) => {
const location = useLocation();
const navbarRef = useRef<HTMLDivElement>(null);
const [pos, setPos] = useState({ left: 0, width: 0 });
const handleActiveLine = useCallback((): void => {
if (navbarRef && navbarRef.current) {
const activeNavbarLink = navbarRef.current.querySelector<HTMLElement>(
".tdp-navbar__item.active"
);
console.log(activeNavbarLink);
if (activeNavbarLink) {
setPos({
left: activeNavbarLink.offsetLeft,
width: activeNavbarLink.offsetWidth,
});
}
}
}, []);
useEffect(() => {
handleActiveLine();
}, [location]);
return (
<>
<div className="tdp-navbar-content shadow">
<div ref={navbarRef} className="tdp-navbar">
<div className="tdp-navbar__left">
<p>Todo+</p>
<CustomLink to="/">About</CustomLink>
<CustomLink to="/login">Login</CustomLink>
</div>
<div className="tdp-navbar__right">
<button className="tdp-button tdp-button--primary tdp-button--border">
<div className="tdp-button__content">
<Link to="/register">Register</Link>
</div>
</button>
<button className="tdp-button tdp-button--primary tdp-button--default">
<div className="tdp-button__content">
<Link to="/login">Login</Link>
</div>
</button>
</div>
<div
className="tdp-navbar__line"
style={{ left: pos.left, width: pos.width }}
/>
</div>
</div>
<main className="page">{children}</main>
</>
);
};
export default Layout;
// CustomLink.tsx
import React, { useEffect, useState } from "react";
import { useLocation, useHistory } from "react-router-dom";
interface Props {
to: string;
}
const CustomLink: React.FC<Props> = ({ to, children }) => {
const location = useLocation();
const history = useHistory();
const [active, setActive] = useState(false);
useEffect(() => {
if (location.pathname === to) {
setActive(true);
} else {
setActive(false);
}
}, [location, to]);
return (
// eslint-disable-next-line react/button-has-type
<button
className={`tdp-navbar__item ${active ? "active" : ""}`}
onClick={(): void => {
history.push(to);
}}
>
{children}
</button>
);
};
export default CustomLink;
但它不像我想要的那样工作。所以我打开 Chrome Devtool 并调试,我意识到当我点击 CustomLink
第一个时,querySelector()
fromNavbar
会返回 null。CustomLink
但是,如果我多次单击相同的内容,它将正确返回,如下面的屏幕截图:
如何querySelector()
从第一次获得正确的回报?谢谢!
解决方案
这是因为会在之前handleActiveLine
触发setActive(true)
CustomLink.tsx
在 中添加回调CustomLink.tsx
:
const CustomLink: React.FC<Props> = ({ onActive }) => {
useEffect(() => {
if (active) {
onActive();
}
}, [active]);
}
在 Navbar.tsx
:
const Layout: React.FC = ({ children }) => {
function handleOnActive() {
// do your query selector here
}
// add onActive={handleOnActive} to each CustomLink
return <CustomLink onActive={handleOnActive} />
}
推荐阅读
- spring-boot - 服务层与控制器层解耦的设计模式最佳实践 Spring boot
- python - 从 url 响应中读取带有 pandas 的 Excel 文件
- api - .net 核心将 null 转换为空字符串以响应 ConfigureServices
- javascript - 如何在 Adobe Acrobat PDF 中突出显示/复制多个文本元素
- python - 逻辑回归模型(二进制)交叉表错误 = 传递值的形状问题
- python - AttributeError:“函数”对象在尝试从函数访问变量时没有属性错误
- apache-kafka - Flink 和非键控窗口状态
- java - 在映射超类中处理 Hibernate 持久性
- javascript - Eclipse IDE v2020-12 (4.18.0) 坚持我的 javascript 文件之一是 HTML 文件,并将每次使用 && 标记为无效字符
- python - Visual Studio Code 中的 Python Quandl 输出