- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有 here完美运行的文本动画。我现在要添加的是 Intersection Observer,这样动画只有在我向下滚动到 Box 时才会开始。
所以我为实现这一点所做的是:我使用 react 钩子(Hook) useRef 用作对我想要观察的元素的引用,并将其应用到我的 Box 中,其中 ref={containerRef}。然后声明了一个回调函数,它接收一个 IntersectionObserverEntries 数组作为参数,在这个函数中,我采用第一个也是唯一一个条目并检查它是否与视口(viewport)相交,如果是,那么它调用 setIsVisible 并使用 entry.isIntersecting (真假)。之后,我添加了 react 钩子(Hook) useEffect 并使用回调函数和我之前创建的选项创建了一个观察者构造函数。我在一个名为 useElementOnscreen 的新钩子(Hook)中实现了逻辑。
它正在工作,但我收到警告但无法解决:
1.初始代码tsx文件
const useElementOnScreen = <T,>(options: T): [MutableRefObject<HTMLDivElement | null>, boolean] => {
const containerRef = useRef<HTMLDivElement | null>(null);
const [isVisible, setIsVisible] = useState(false);
const callbackFunction = (entries: IntersectionObserverEntry[]) => {
const [entry] = entries;
setIsVisible(entry.isIntersecting);
};
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, options);
if (containerRef.current) observer.observe(containerRef?.current);
return () => {
if (containerRef.current) observer.unobserve(containerRef?.current);
};
}, [containerRef, options]);
return [containerRef, isVisible];
};
在这里我收到警告:
if (containerRef.current) observer.unobserve(containerRef?.current);
警告是:
(property) MutableRefObject<HTMLDivElement | null>.current: HTMLDivElement
The ref value 'containerRef.current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy 'containerRef.current' to a variable inside the effect, and use that variable in the cleanup function.
eslint
react-hooks/exhaustive-deps
const useElementOnScreen = <T,>(options: T): [MutableRefObject<HTMLDivElement | null>, boolean] => {
let observerRefValue: Element | null = null; // <-- variable to hold ref value
const containerRef = useRef<HTMLDivElement | null>(null);
const [isVisible, setIsVisible] = useState(false);
const callbackFunction = (entries: IntersectionObserverEntry[]) => {
const [entry] = entries;
setIsVisible(entry.isIntersecting);
};
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, options);
if (containerRef.current) observer.observe(containerRef?.current);
observerRefValue = containerRef.current; // <-- save ref value
return () => {
if (observerRefValue) observer.unobserve(observerRefValue); // <-- use saved value
};
}, [containerRef, options]);
return [containerRef, isVisible];
};
但话又说回来,我收到警告:
observerRefValue = containerRef.current; // <-- save ref value
(property) MutableRefObject<HTMLDivElement | null>.current: HTMLDivElement | null
Assignments to the 'observerRefValue' variable from inside React Hook useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside useEffect.eslintreact-hooks/exhaustive-deps
3. 现在我更改了我的let observerRefValue: Element | null = null;
至const [observerRefValue, setObserverRefValue] = useState<Element | null>(null);
警告消失了,它的工作!setObserverRefValue
在任何地方,我都会收到警告 'setObserverRefValue' is assigned a value but never used
.
const useElementOnScreen = <T,>(options: T): [MutableRefObject<HTMLDivElement | null>, boolean] => {
const [observerRefValue, setObserverRefValue] = useState<Element | null>(null);
const containerRef = useRef<HTMLDivElement | null>(null);
const [isVisible, setIsVisible] = useState(false);
const callbackFunction = (entries: IntersectionObserverEntry[]) => {
const [entry] = entries;
setIsVisible(entry.isIntersecting);
};
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, options);
if (containerRef.current) observer.observe(containerRef?.current);
return () => {
if (observerRefValue) observer.unobserve(observerRefValue); // <-- use saved value
};
}, [observerRefValue, containerRef, options]);
return [containerRef, isVisible];
};
这只是一个警告,但我的问题是:
'setObserverRefValue' is assigned a value but never used
有没有办法在我的例子中使用它,所以我可以摆脱警告?
最佳答案
亚当发布的内容是解决此问题的好方法。我在我的代码库中使用完全相同的代码模式。 ref 不是钩子(Hook)的一部分,而是作为 Prop 传递的。这样钩子(Hook)只包含检查 Node
的逻辑。 ref
所指向的是否在屏幕上可见。到目前为止,这对我们有用。
现在在您的代码中,钩子(Hook)负责处理 ref
也。然后附上 ref
钩子(Hook)返回的任何值。 (有兴趣在评论中了解您为什么遵循这种模式。)
我将讨论您提供的所有三个代码片段:
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, options);
if (containerRef.current) observer.observe(containerRef?.current);
observerRefValue = containerRef.current; // <-- save ref value
return () => {
if (observerRefValue) observer.unobserve(observerRefValue); // <-- use saved value
};
}, [containerRef, options]);
首先,您可以使用
containerRef
作为依赖项,但让我提醒您更改
containerRef.current
不会触发渲染。它不是
state
变量并且不会导致重新渲染。所以如果
ref
更改,您无法确定
useEffect
回调将再次运行,因此您的
ref
中可能有错误的值。容器。
The ref value 'containerRef.current' will likely have changed by thetime this effect cleanup function runs. If this ref points to a noderendered by React, copy 'containerRef.current' to a variable insidethe effect, and use that variable in the cleanup function.
function Box() {
const ref = useRef();
useEffect(() => {
console.log("mount 1 ", ref.current);
return () => setTimeout(() => console.log("unmount 1 ", ref.current), 0);
}, []);
useEffect(() => {
const element = ref.current;
console.log("mount 2 ", element);
return () => setTimeout(() => console.log("unmount 2 ", element), 0);
}, []);
return (
<div ref={ref} className="box">
Box
</div>
);
}
export default function App() {
let [state, setState] = useState(true);
useEffect(() => {
setTimeout(() => setState(false), 1000);
}, []);
return (
<div className="App">
<p>useEffect useRef warning</p>
{state && <Box />}
</div>
);
}
第一个
useEffect
的输出返回函数将是
unmount 1 null
, 因为值已经改变了,但是效果回调是不知道的。
const useOnScreen = <T,>(options: T): [MutableRefObject<HTMLDivElement | null>, boolean] => {
const containerRef = useRef<HTMLDivElement | null>(null);
const [isVisible, setIsVisible] = useState(false);
const callbackFunction = (entries: IntersectionObserverEntry[]) => {
const [entry] = entries;
setIsVisible(entry.isIntersecting);
};
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, options);
const refCopy = containerRef.current;
if (refCopy) observer.observe(refCopy);
return () => {
if (refCopy) observer.unobserve(refCopy);
};
}, [options]);
return [containerRef, isVisible];
};
上面的代码解决了所有警告。这正是 linter 所建议的。引用指向
DOM Element
,卸载时为
null
,但是通过保留变量的副本,我们仍然可以访问它并使用它做任何我们想做的事情。
observerRefValue
在这里是一个非特殊变量(不是 ref
变量也不是 state
变量),对它所做的更改将在每次渲染时被清除。所以你不能依赖它的值(value)。每次重新渲染后,它都会被赋值为 null
正如最初定义的那样。因此发出警告。这也可能对您的用例没有帮助。null
但从未更新为任何其他值。以下条件将始终为假,您的预期代码将不会仅运行:if (observerRefValue)
这也无助于您的用例。此外,如果不需要,您不应该使用状态变量。
关于javascript - 来自 React Hook 内部的变量 useEffect 将在每次渲染后丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73085745/
我知道没有数组的 useEffect() 只在第一次渲染时运行回调。 那么useEffect(()=>{},[])和没有useEffect()的区别是什么。 我的意思是: function myCom
我的场景很少,我想了解渲染和性能方面的差异。 下面显示的示例是一个简单的函数,但请考虑一个更复杂的函数以及一个异步函数。 场景 1:定义函数并在 useEffect 中调用它。 useEffect((
我需要添加一些与 React 之外的对象交互的事件处理程序(以 Google map 为例)。 在这个处理函数内部,我想访问一些可以发送给这个外部对象的状态。 如果我将状态作为依赖项传递给效果,它可以
要限制 useEffect 在第一个渲染上运行,我们可以这样做: const isFirstRun = useRef(true); useEffect (() => { if (isF
我有一个产品组件,它显示某个类别的产品。CategoryId 从路由参数中获取,然后用户可以对产品进行分页。所以有2个useEffect,一个是改变categoryId的时候,另一个是改变当前页码的时
我有一个产品组件,它显示某个类别的产品。CategoryId 从路由参数中获取,然后用户可以对产品进行分页。所以有2个useEffect,一个是改变categoryId的时候,另一个是改变当前页码的时
我的状态宽度随着窗口大小的调整而变化,showFilters作为 Prop 从true变为false。我想在卸载时删除监听器。因此,我为每个条件使用了三个 useState。那么,我可以做任何重构来在
我正在开发一个基于对象键管理字符串数组的函数。假设它看起来像这样: import React, { useState, useEffect } from "react"; import FieldCo
新的 React Hooks 功能很酷,但有时会让我感到困惑。特别是,我将此代码包装在 useEffect Hook 中: const compA = ({ num }) => { const [
我想将其转换为 useEffect钩: 代码 componentDidMount () { this.messagesRef.on('child_added', snapshot => {
这是我的代码部分。一切正常,但 eslint 给出错误。 React Hook useEffect has missing dependencies: 'dispatch' and 'getData'
当组件安装时,我需要从两个 API 端点获取数据。现在我有: useEffect(() => { dispatch(loadSomeDataOne()); }, [dispatch])
当组件安装时,我需要从两个 API 端点获取数据。现在我有: useEffect(() => { dispatch(loadSomeDataOne()); }, [dispatch])
在 React DOCs 中,关于 useEffect() 钩子(Hook),我们得到: “使用 useEffect 安排的效果不会阻止浏览器更新屏幕。” Tip Unlike componentDi
我一直试图了解何时取消订阅(useEffect 中的回调)被准确调用。 这是codepen链接:https://codepen.io/deen_john/pen/eYmNdMy 代码 : const
当对状态、效果、上下文等使用钩子(Hook)时,我这样做: import React, { useState, useEffect, useContext } from 'react'; 但是,我注意
我正在尝试像下面这样的 useEffect 示例: useEffect(async () => { try { const response = await fetch(`ht
我在我的 React 应用中构建了一个简单的点赞、书签功能。 const [liked, setLiked] = useState(); const [bookmarked, setBookmarke
我想了解为什么在代码块的底部使用 useEffect,以及它的用途。我认为它与组件生命周期和避免无限循环有关,但我无法完全理解它并全面了解这一切。如果有人能向我解释幕后发生的事情,以及 useEffe
useEffect(() => { return history.replace({ pathname: "path/A", }); }, []); useEffe
我是一名优秀的程序员,十分优秀!