【发布时间】:2020-11-03 03:02:53
【问题描述】:
我正在构建一个简单的 React 滑块,它将通过 ref 向其父级公开内部方法,我在怀疑是陈旧的闭包时遇到了麻烦,但我无法完全理解实际发生的情况.希望有人能帮助我理解这里。
这是我想要工作的代码的简化版本:
const Slider = forwardRef((props, ref) => {
const sliderRef = useRef();
const [slides, dispatchSlides] = useReducer(reducer, []);
sliderRef.current = {
countSlides: () => {
return slides.length
},
};
useImperativeHandle(ref, () => sliderRef.current);
return null;
安装此组件后,其子组件将使用 IntersectionObserver 渲染并填充 slides 减速器及其位置和可见性信息。这部分有效,因此为简单起见,我将其排除在此示例之外。为了我们的缘故,假设slides 在挂载后立即被对象填充,并且用户将在填充slides 之后很久之后从父组件手动调用countObjects。
在父组件中,如果我从 ref 执行countSlides,我将始终看到slides.length === 0,无论实际存在多少张幻灯片。我认为这是因为原来的 countSlides 方法是一个陈旧的闭包。
现在,我不完全理解的是,如果我调整这条线:
useImperativeHandle(ref, () => sliderRef.current);
到这里:
useImperativeHandle(ref, () => () => {
countSlides: () => sliderRef.current.countSlides()
});
陈旧的关闭已修复,一切都按预期工作。但这是重复的代码,我只是不确定这两种情况有什么不同。我不想重复自己在 useImperativeHandle 钩子中重新定义许多方法,但更重要的是,我想了解上面两个示例之间的区别。
谢谢!
编辑添加完整示例:
【问题讨论】:
-
能否添加使用 Slider 组件的代码?我想看看它的用法
-
如果可能的话,我希望看到您的组件的完整版本,因为我尝试使用您使用的两种方法,并且都对我有用。 codesandbox.io/s/use-imperative-handle-7ij5k?file=/src/App.tsx
-
好的,所以我刚刚浏览了您的沙箱并弄清楚了为什么您的沙箱有效,而我的无效。您正在有效地创建与我所展示的工作相同的模式,但在不同的地方。这一行创建了一个闭包:
onClick={() => {countRef1.current.increase();}}解决了这个问题。但是.. 我的代码是这样做的:onClick={countRef1?.current?.increase}。另外,我用一个完整的例子更新了我的帖子来演示。所以,原来的问题依然存在,只是……移动了。
标签: javascript reactjs react-hooks