Javascript 如何在渲染前使用React挂钩响应道具更改
我试图使用一个功能组件和React钩子来实现一个简化的自动滚动器,当子内容溢出时,它会自动将容器滚动到底。但是,只有当滚动条已经位于底部时,才会发生自动滚动(例如,如果用户向上滚动以查看输出,则当新内容进入时,滚动位置不应改变) 我知道如何通过使用refs和对clientHeight、scrollTop和scrollHeight执行计算来实现自动滚动行为 我的问题是,在重新渲染组件之前,我需要计算Javascript 如何在渲染前使用React挂钩响应道具更改,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我试图使用一个功能组件和React钩子来实现一个简化的自动滚动器,当子内容溢出时,它会自动将容器滚动到底。但是,只有当滚动条已经位于底部时,才会发生自动滚动(例如,如果用户向上滚动以查看输出,则当新内容进入时,滚动位置不应改变) 我知道如何通过使用refs和对clientHeight、scrollTop和scrollHeight执行计算来实现自动滚动行为 我的问题是,在重新渲染组件之前,我需要计算shouldAutoScroll()检查 我的流程需要如下所示: <container>
shouldAutoScroll()
检查
我的流程需要如下所示:
<container>
{props.children}
</container>
When props.children changes:
1. Check if the scrollbar is near the bottom and store the result
2. Update container to reflect the new props.children
3. If the check from step 1 is true, scroll to the bottom
我需要保持组件的通用性,这样无论是什么类型的组件或元素props.children,它都可以自动滚动。在某些情况下,对props.chldren的更改可能是一行。在其他情况下,它可能是20行,也可能是一个图像
如果我使用的是旧样式的类组件,我可以在componentWillReceiveProps()中进行计算。我如何用钩子复制它?我发现了一个可行的解决方案,但似乎有点混乱 解决方案是在容器的
onScroll()
事件期间计算并更新shouldAutoScroll()
。这看起来很混乱,因为我捕获了大量无用的中间滚动信息,而我所关心的只是更新开始时(但在组件重新渲染之前)的滚动位置
完整代码:
import React, { useRef, useEffect, useLayoutEffect } from 'react';
import styles from './AutoScroller.module.scss';
export function AutoScroller({children, className=''}) {
const classNames = `${styles.default} ${className}`;
const containerRef = useRef(null);
const shouldAutoScroll = useRef(false);
function updateShouldAutoScroll(element, tolerance) {
const {scrollHeight, scrollTop, clientHeight} = element;
const result = scrollHeight - scrollTop <= clientHeight + tolerance;
shouldAutoScroll.current = result;
}
function onContainerScroll(e) {
updateShouldAutoScroll(e.target, 25)
}
useEffect(function autoScroll() {
if (shouldAutoScroll.current) {
const element = containerRef.current;
element.scrollTop = element.scrollHeight;
}
});
return (
<div className={classNames} ref={containerRef} onScroll={onContainerScroll}>
{children}
</div>
)
}
import React,{useRef,useffect,useLayoutEffect}来自'React';
从“/AutoScroller.module.scss”导入样式;
导出函数AutoScroller({children,className='''}){
const classNames=`${styles.default}${className}`;
const containerRef=useRef(null);
const shouldAutoScroll=useRef(false);
函数更新Shouldautoscroll(元素,公差){
常量{scrollHeight,scrollTop,clientHeight}=元素;
const result=scrollHeight-scrollTop您可以在中复制它吗?
import React, { useRef, useEffect, useLayoutEffect } from 'react';
import styles from './AutoScroller.module.scss';
export function AutoScroller({children, className=''}) {
const classNames = `${styles.default} ${className}`;
const containerRef = useRef(null);
const shouldAutoScroll = useRef(false);
function updateShouldAutoScroll(element, tolerance) {
const {scrollHeight, scrollTop, clientHeight} = element;
const result = scrollHeight - scrollTop <= clientHeight + tolerance;
shouldAutoScroll.current = result;
}
function onContainerScroll(e) {
updateShouldAutoScroll(e.target, 25)
}
useEffect(function autoScroll() {
if (shouldAutoScroll.current) {
const element = containerRef.current;
element.scrollTop = element.scrollHeight;
}
});
return (
<div className={classNames} ref={containerRef} onScroll={onContainerScroll}>
{children}
</div>
)
}