React .scrollLeft 无法读取空值
2022-06-14
3176
我尝试使用 React 中的按钮访问水平滚动条,但结果发现它无法工作,因为无法读取
.scrollLeft
的空值。
<>
<div className="containerOuterSider">
<FaAngleLeft className= "FaAngleLeft" onClick={slide('left')}/>
<div id="container3" className="container3">
{products &&
products
.map((product) => (
<AAsOfLowNav key={product._id} product={product} />
))
.reverse()}
</div>
<FaAngleRight className="FaAngleRight" onClick={slide('right')}/>
</div>
</>
主要功能是
function slide(direction) {
var container = document.getElementById('container3');
let scrollCompleted = 0;
var slideVar = setInterval(function() {
if (direction === 'left') {
container.scrollLeft -= 10;
} else {
container.scrollLeft += 10;
}
scrollCompleted += 10;
if (scrollCompleted >= 100) {
window.clearInterval(slideVar);
}
}, 50);
}
我遇到的错误是:
Uncaught TypeError: Cannot read properties of null (reading 'scrollLeft') at LowerCatNav.js:31:1 Uncaught TypeError: Cannot read properties of null (reading 'scrollLeft') at LowerCatNav.js:33:1
我该如何做?我应该使用钩子还是其他什么?
2个回答
问题
您在渲染时立即调用
slide
函数:
<FaAngleLeft
className="FaAngleLeft"
onClick={slide('left')} // <-- immediately invoked when rendered
/>
...
<FaAngleRight
className="FaAngleRight"
onClick={slide('right')} // <-- immediately invoked when rendered
/>
React 组件尚未完全渲染并推送到 DOM,因此对 DOM 的查询(即
document.getElementById('container3')
)返回
null
。
解决方案
修复点击处理程序,以便
slide
不会立即被调用。
<FaAngleLeft
className="FaAngleLeft"
onClick={() => slide('left')} // <-- asynchronously invoked when clicked
/>
...
<FaAngleRight
className="FaAngleRight"
onClick={() => slide('right')} // <-- asynchronously invoked when clicked
/>
直接查询 DOM 中的 DOMNodes 被视为 React 反模式,为此使用 React ref。
示例:
...
const containerRef = React.useRef(); // <-- (1) create Ref
const sliderTimerRef = React.useRef();
useEffect(() => {
return () => {
// clear any running intervals on component unmount
clearInterval(sliderTimerRef.current);
};
}, []);
...
function slide(direction) {
// clear any previously set intervals and reset scrollCompleted
clearInterval(sliderTimerRef.current);
let scrollCompleted = 0;
sliderTimerRef.current = setInterval(function() {
const container = containerRef.current; // <-- (3) access current ref value
if (direction === 'left') {
container?.scrollLeft -= 10; // <-- (4) Optional Chaining null check
} else {
container?.scrollLeft += 10; // <-- (4) Optional Chaining null check
}
scrollCompleted += 10;
if (scrollCompleted >= 100) {
clearInterval(sliderTimerRef.current);
}
}, 50);
}
...
return (
<>
<div className="containerOuterSider">
<FaAngleLeft className="FaAngleLeft" onClick={() => slide('left')}/>
<div
ref={containerRef} // <-- (2) attach ref to element
id="container3"
className="container3"
>
{products
.map((product) => (
<AAsOfLowNav key={product._id} product={product} />
))
.reverse()
}
</div>
<FaAngleRight className="FaAngleRight" onClick={() => slide('right')}/>
</div>
</>
);
Drew Reese
2022-06-14
-
slide
在#container3
尚未创建时被调用。
将onClick={slide(...)
更改为onClick={() => slide(...)
-
应避免访问全局元素(例如通过 id)。
首选ref
/createRef
/useRef
来访问属于您的组件的元素。
Ruslan Tushov
2022-06-14