javascript - 如何在功能组件中混合使用 useCallback 和 useRef
问题描述
我对 React 很陌生,并且正在研究无限滚动组件。多个组件将使用无限滚动并且需要一起同步(即,以编程方式滚动一个元素也会滚动其他组件)。
所以我创建了ScrollProvider
它维护组件之间的滚动状态(即使它们被重新渲染),并且较低级别的钩子useScrollSync.
useScrollState 返回一个 ref 和一个 handleScroll 回调,它们修改滚动提供程序中的状态。这一切都很好。但是,我想单独测量一个组件的大小。React 团队提供的示例显示了一个回调,因为它肯定会在组件安装后执行,并且元素不会为空。问题是 div 已经有一个来自 useScrollSync 钩子的引用。
核心问题
如果除了在其上使用滚动同步之外,我还想测量我的 div,如何将回调 ref 和其他 ref 分配给它?考虑到一个元素只能有一个 div,是否有这种模式?
一些(简化的)代码:
滚动提供者
const ScrollContext = React.createCreateContext();
const ScrollProvider = ({initialScrollTop, initialScrollLeft}) => {
const controlledElements = useRef(new Map());
const scrollPositions = useRef({
scrollTop: initialScrollTop,
scrollLeft: initialScrollLeft,
controllingElementKey: null
});
const register = (key, controlledElementRef) => {
controlledElements.current.set(key, controlledElementRef);
}
const handleScrollHOF = (key) => {
return () => {
scrollPositions.controllingElementKey = key;
//some scrolling logic
}
}
return {register, scrollPositions, handleScrollHOF};
}
使用滚动同步
const useScrollSync = () => {
const scrollContext = useContext(ScrollContext);
const elementRef = useRef(null);
const keyRef = useRef({key: Symbol()}); // this probably could also be useState
useEffect(() => {
scrollContext.register(keyRef, elementRef);
}, []);
return {ref: elementRef, handleScroll: handleScrollHOF(keyRef.current)};
}
SomeComponent(第一轮)
const SomeComponent = () => {
// this would be within the provider tree
const {ref, handleScroll} = useScrollSync();
return (
<div onScroll={handleScroll} ref={ref}>some stuff</div>
)
}
现在的挑战是添加一个测量钩子......
使用测量
const useMeasurements = () => {
// something like this, per the React team's Hooks FAQ
const [measurements, setMeasurements] = useState(null);
const measurementRef = useCallback((element) => {
if(element !== null) {
setMeasurements(element.getBoundingClientRect());
}
});
return {measurementRef, measurements};
}
为了将其添加到 SomeComponent... SomeComponent (Round 2)
const SomeComponent = () => {
// this would be within the provider tree
const {ref, handleScroll} = useScrollSync();
const {measurementRef, measurements} = useMeasurements();
// I cannot assign measurementRef to this same div,
// and changing useMeasurements to just measure an injected ref winds up
// with that ref being null and it never being recalculated
return (
<div onScroll={handleScroll} ref={ref}>some stuff</div>
)
}
我在这里有点碰壁,或者我只是太累了。关于如何超越这一点的任何想法?
解决方案
我看到的主要问题是您没有在 useMeasurement 中引用可行的参考。此外,useCallback 在创建 DOM 之前作为渲染的一部分同步执行。您需要在另一个 useEffect 挂钩中引用您的元素。
推荐阅读
- python - Python修改日志消息信息?
- mysql - 如何使用 JSON 对象的结果创建 SQL 查询并避免重复条目 (DISTINCT)
- javafx - 如何自定义日期选择器的日历弹出窗口以显示在特定日期而不是当前日期
- css - 样式表未加载到作为 PKG 发布的模块化 JavaFX 应用程序中
- python - 为 VGGFace 实现 lambda 预处理函数
- javascript - 我无法在 REACTJS 上使用 onChange、useState 和扩展运算符输入我的输入
- javascript - 将getUserMedia和getDisplayMedia中的mediaStreams组合在一起时,同步函数中的异步javascript?
- javascript - Javascript setInterval闪烁
- python - 在numpy数组中集体删除非三行
- python - 向 SQLAlchemy 数据库添加条目会触发`sqlite InterfaceError: Error binding parameter 0 - 可能是不受支持的类型`