我正在尝试运行一个函数来检查任何DOM节点与其背景的对比,将对节点本身的引用作为参数传递。但是在初始渲染时,ref值保持null
,我不明白为什么。
我知道使用useLayoutEffect
代替useEffect
应该同步触发。另外,也许问题出在ref本身,但是useRef
不应该这样做吗?
Here's a sandbox with the full code。
这是组成部分:
function App() {
const ref = useRef(null);
const contrast = useContrast(ref);
return (
<div className="App">
<h1 ref={ref}>Contrast: {contrast}</h1>
</div>
);
}
以及自定义钩子部分:
export default function useContrast(ref) {
const [contrast, setContrast] = useState("");
if (!!ref.current) {
useLayoutEffect(() => {
const contrast = contrastValidation(
getForegroundColor(ref.current),
getBackgroundColor(ref.current)
);
setContrast(contrast);
});
return ref.current;
}
return contrast;
}
它应该在此处显示一些对比度值:<h1 ref={ref}>Contrast: {contrast}</h1>
,但我得到的一切都是null
(因为默认情况下它是用useRef
定义的。)
答案 0 :(得分:2)
ref.current
将在给useLayoutEffect
的函数中设置,但不会在它之前设置,因此您不能执行if (!!ref.current) { ... }
来有条件地使用该挂钩。您根本不应将钩子放在条件逻辑中。
这将按您期望的方式工作,因为在给浏览器绘画之前,useLayoutEffect
赋予的函数内部发生的状态更新将被同步刷新。
export default function useContrast(ref) {
const [contrast, setContrast] = useState("");
useLayoutEffect(() => {
const contrast = contrastValidation(
getForegroundColor(ref.current),
getBackgroundColor(ref.current)
);
setContrast(contrast);
});
return contrast;
}