我想创建一个对元素的引用,将其保存为状态并在其他地方使用。这是我到目前为止的内容:
const Header = () => {
const topElement = useRef();
const { setRootElement } = useScrollToTop();
useEffect(() => {
setRootElement(topElement);
}, []);
return (
<div ref={topElement}>
...
</div>
)
}
useScrollToTop
钩子:
export const useScrollToTop = () => {
const [rootElement, setRootElement] = useState();
const scrollToTop = () => {
rootElement.current.scrollIntoView();
};
return {
scrollToTop: scrollToTop,
setRootElement: setRootElement
};
};
在另一个组件中:
const LongList = () => {
const { scrollToTop } = useScrollToTop();
return (
<div>
....
<button onClick={() => scrollToTop()} />
</div>
);
}
setRootElemet
可以正常工作,它保存了我传递给它的元素,但是当我调用scrollToTop()
时,该元素是未定义的。我在这里想念什么?
答案 0 :(得分:0)
问题可能是topElement
最初为null,而useEffect将触发setRootElement
为null。您需要将topElement
保留在状态变量中,并检查其何时更改并将JSX内部的值设置为
const [topElement, setTopElement] = useState(null);
useEffect(() => {topElement && setRootElement(topElement);}, [topElement])
return (
<div ref={(ref) => setTopElement(ref)}>
...
</div>
);
答案 1 :(得分:0)
由于挂钩实际上只是函数,因此在调用之间没有共享的状态。每次调用useScrollToTop
时,都会得到一个具有自己的scrollToTop
和setRootElement
的新对象。当您在useScrollToTop
中调用LongList
时,将永远不会使用返回的setRootElement
,因此该实例rootElement
将永远没有值。
您需要做的是致电useScrollToTop
,并将返回的项目传递给它们各自的组件。另外,您可以直接使用ref并返回它,而不是在元素的挂钩中使用状态。
将这些内容放在一起,假设您具有类似以下内容的App结构:
挂钩:
export const useScrollToTop = () => {
const rootElement = useRef();
const scrollToTop = () => {
rootElement.current.scrollIntoView();
};
return {
scrollToTop,
rootElement,
};
};
应用程序:
...
const { scrollToTop, rootElement } = useScrollToTop();
return (
...
<Header rootElementRef={rootElement} />
<LongList scrollToTop={scrollToTop} />
...
);
标题:
const Header = ({ rootElementRef }) => {
return (
<div ref={rootElementRef}>
...
</div>
);
}
长列表:
const LongList = ({ scrollToTop }) => {
return (
<div>
...
<button onClick={() => scrollToTop()} />
</div>
);
}