我创建了一个自定义钩子,以便在滚动组件时将元素滚动回视图中。
export const useComponentIntoView = () => {
const ref = useRef();
const {current} = ref;
if (current) {
window.scrollTo(0, current.offsetTop );
}
return ref;
}
现在我正在一个功能组件中使用它,例如
<div ref={useComponentIntoView()}>
所以第一次电流总是为空,我知道组件仍未挂载,因此值为 null . 但是我们可以做些什么来在我的自定义钩子中始终获取此值,因为仅在第一次导航时组件滚动不起作用.有没有解决这个问题的方法.
我们需要从 useEffect
中读取ref
,当它已经被分配时。为了仅在挂载时调用它,我们传递一个空的依赖项数组:
const MyComponent = props => {
const ref = useRef(null);
useEffect(() => {
if (ref.current) {
window.scrollTo(0, ref.current.offsetTop);
}
}, []);
return <div ref={ref} />;
};
为了在组件中摆脱此功能,在它自己的 Hook 中,我们可以这样做:
const useComponentIntoView = () => {
const ref = useRef(null);
useEffect(() => {
if (ref.current) {
window.scrollTo(0, ref.current.offsetTop);
}
}, []);
return ref;
};
const MyComponent = props => {
const ref = useComponentIntoView();
return <div ref={ref} />;
};
我们还可以在进行一定更改后运行useEffect
钩子。在这种情况下,我们需要传递给它的依赖项数组,一个属于状态的变量。此变量可以属于同一组件或祖先组件。例如:
const MyComponent = props => {
const [counter, setCounter] = useState(0);
const ref = useRef(null);
useEffect(() => {
if (ref.current) {
window.scrollTo(0, ref.current.offsetTop);
}
}, [counter]);
return (
<div ref={ref}>
<button onClick={() => setCounter(counter => counter + 1)}>
Click me
</button>
</div>
);
};
在上面的示例中,每次单击按钮时,它都会更新计数器状态。此更新会触发新的呈现,并且由于计数器值自上次调用 useEffect
以来发生了变化,它将运行useEffect
回调。
正如您所提到的,ref.current
null
,直到组件挂载之后。这是您可以使用useEffect
的地方 - 它将在组件挂载后触发,即:
const useComponentIntoView = () => {
const ref = useRef();
useEffect(() => {
if (ref.current) {
window.scrollTo(0, ref.current.offsetTop );
}
});
return ref;
}