我有一个聊天小部件,每当我向上滚动时,它就会弹出一个消息数组。我现在面临的问题是,当消息加载时,滑块固定在顶部。我想让它关注上一个数组的最后一个索引元素。我发现我可以通过传递索引来进行动态引用,但我也需要知道使用哪种滚动函数来实现这一点

 handleScrollToElement(event) {
    const tesNode = ReactDOM.findDOMNode(this.refs.test)
    if (some_logic){
      //scroll to testNode      
    }
  }

  render() {

    return (
      <div>
        <div ref="test"></div>
      </div>)
  }

当前回答

也许有人会遇到像我这样的情况

https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node

如何度量DOM节点? 测量DOM节点位置或大小的一种基本方法是使用回调ref。每当ref附加到不同的节点时,React就会调用该回调。下面是一个小演示:

function MeasureExample() {
  const [height, setHeight] = useState(0);

  const measuredRef = useCallback(node => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);// you can scroll in this line 
    }
  }, []);

  return (
    <>
      <h1 ref={measuredRef}>Hello, world</h1>
      <h2>The above header is {Math.round(height)}px tall</h2>
    </>
  );
}

在本例中,我们没有选择useRef,因为对象引用不会通知我们当前引用值的更改。使用回调引用可以确保即使稍后子组件显示了被测量的节点(例如,在响应单击时),我们仍然会在父组件中得到关于它的通知,并可以更新测量值。

注意,我们将[]作为依赖数组传递给useCallback。这确保了我们的ref回调在重新渲染之间不会改变,所以React不会不必要地调用它。

在这个例子中,回调ref只会在组件挂载和卸载时被调用,因为呈现的组件在任何重新呈现器中都保持存在。如果你想在组件调整大小时收到通知,你可以使用ResizeObserver或在其上构建的第三方Hook。

其他回答

你可以这样尝试:

 handleScrollToElement = e => {
    const elementTop = this.gate.offsetTop;
    window.scrollTo(0, elementTop);
 };

 render(){
  return(
      <h2 ref={elem => (this.gate = elem)}>Payment gate</h2>
 )}

2019年7月-专用钩子/函数

专用的钩子/函数可以隐藏实现细节,并为组件提供简单的API。

React 16.8 +功能组件

const useScroll = () => {
  const elRef = useRef(null);
  const executeScroll = () => elRef.current.scrollIntoView();

  return [executeScroll, elRef];
};

在任何功能组件中使用它。

const ScrollDemo = () => {
    const [executeScroll, elRef] = useScroll()
    useEffect(executeScroll, []) // Runs after component mounts
    
    return <div ref={elRef}>Element to scroll to</div> 
}

完整的演示

React 16.3 +类组件

const utilizeScroll = () => {
  const elRef = React.createRef();
  const executeScroll = () => elRef.current.scrollIntoView();

  return { executeScroll, elRef };
};

在任何类组件中使用它。

class ScrollDemo extends Component {
  constructor(props) {
    super(props);
    this.elScroll = utilizeScroll();
  }

  componentDidMount() {
    this.elScroll.executeScroll();
  }

  render(){
    return <div ref={this.elScroll.elRef}>Element to scroll to</div> 
  }
} 

完整的演示

对于读到这篇文章的人来说,如果他们没有那么幸运地使用上述解决方案,或者只是想要一个简单的即时解决方案,那么这个软件包对我来说很有用:https://www.npmjs.com/package/react-anchor-link-smooth-scroll。黑客快乐!

还可以使用scrollIntoView方法滚动到给定元素。

handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
 if (some_logic){
  tesNode.scrollIntoView();
  }
 }

 render() {
  return (
   <div>
     <div ref="test"></div>
   </div>)
}

如果有人在使用Typescript,下面是Ben Carp的答案:

import { RefObject, useRef } from 'react';

export const useScroll = <T extends HTMLElement>(
  options?: boolean | ScrollIntoViewOptions
): [() => void, RefObject<T>] => {
  const elRef = useRef<T>(null);
  const executeScroll = (): void => {
    if (elRef.current) {
      elRef.current.scrollIntoView(options);
    }
  };

  return [executeScroll, elRef];
};