在react.js中渲染后滚动到页面顶部

我有一个问题,我不知道怎么解决。 在我的react组件中,我在底部显示了一个很长的数据列表和一些链接。 在点击任何链接后,我用新的链接集合填充列表,并需要滚动到顶部

问题是-如何滚动到顶部新集合被渲染?

'use strict';


// url of this component is #/:checklistId/:sectionId


var React = require('react'),
Router = require('react-router'),
sectionStore = require('./../stores/checklist-section-store');




function updateStateFromProps() {
var self = this;
sectionStore.getChecklistSectionContent({
checklistId: this.getParams().checklistId,
sectionId: this.getParams().sectionId
}).then(function (section) {
self.setState({
section,
componentReady: true
});
});


this.setState({componentReady: false});
}


var Checklist = React.createClass({
mixins: [Router.State],


componentWillMount: function () {
updateStateFromProps.call(this);
},


componentWillReceiveProps(){
updateStateFromProps.call(this);
},


render: function () {
if (this.state.componentReady) {
return(
<section className='checklist-section'>
<header className='section-header'>{ this.state.section.name }   </header>
<Steps steps={ this.state.section.steps }/>
<a href=`#/${this.getParams().checklistId}/${this.state.section.nextSection.Id}`>
Next Section
</a>
</section>
);
} else {...}
}
});


module.exports = Checklist;
490330 次浏览

你可以用这样的东西。ReactDom是react的缩写。否则只需React即可。

    componentDidUpdate = () => { ReactDom.findDOMNode(this).scrollIntoView(); }

2019年5月11日更新React 16+

  constructor(props) {
super(props)
this.childDiv = React.createRef()
}


componentDidMount = () => this.handleScroll()


componentDidUpdate = () => this.handleScroll()


handleScroll = () => {
const { index, selected } = this.props
if (index === selected) {
setTimeout(() => {
this.childDiv.current.scrollIntoView({ behavior: 'smooth' })
}, 500)
}
}

由于最初的解决方案是为反应的早期版本提供的,因此这里有一个更新:

constructor(props) {
super(props)
this.myRef = React.createRef()   // Create a ref object
}


componentDidMount() {
this.myRef.current.scrollTo(0, 0);
}


render() {
return <div ref={this.myRef}></div>
}   // attach the ref property to a dom element

这可以,也可能应该使用参考文献来处理:

“…你可以使用ReactDOM。findDOMNode作为一个“逃生舱口”,但我们不推荐它,因为它破坏了封装,在几乎所有情况下,在React模型中都有更清晰的方式来构建代码。”

示例代码:

class MyComponent extends React.Component {
componentDidMount() {
this._div.scrollTop = 0
}


render() {
return <div ref={(ref) => this._div = ref} />
}
}

最后. .我使用:

componentDidMount() {
window.scrollTo(0, 0)
}

编辑:React v16.8+

useEffect(() => {
window.scrollTo(0, 0)
}, [])

你可以在路由器上这样做:

ReactDOM.render((
<Router onUpdate={() => window.scrollTo(0, 0)} history={browserHistory}>
<Route path='/' component={App}>
<IndexRoute component={Home}></IndexRoute>
<Route path="/about" component={About}/>
<Route path="/work">
<IndexRoute component={Work}></IndexRoute>
<Route path=":id" component={ProjectFull}></Route>
</Route>
<Route path="/blog" component={Blog}/>
</Route>
</Router>
), document.getElementById('root'));
onUpdate={() => window.scrollTo(0, 0)}放置滚动顶部。 更多信息请查看:codepen链接

这是唯一对我有用的东西(使用ES6类组件):

componentDidMount() {
ReactDOM.findDOMNode(this).scrollIntoView();
}

这里还有另一种方法,它允许你选择你希望窗口滚动位置重置到的安装组件,而不需要大量复制ComponentDidUpdate/ComponentDidMount。

下面的例子是用ScrollIntoView()包装Blog组件,这样当Blog组件被挂载时,如果路由改变了,那么HOC的ComponentDidUpdate将更新窗口滚动位置。

你可以很容易地将它包裹在整个应用程序中,这样在任何路由改变时,它都会触发一个窗口重置。

ScrollIntoView.js

import React, { Component } from 'react';
import { withRouter } from 'react-router';


export default WrappedComponent => {
class ResetWindowScroll extends Component {
componentDidUpdate = (prevProps) => {
if(this.props.location !== prevProps.location) window.scrollTo(0,0);
}


render = () => <WrappedComponent {...this.props} />
}
return withRouter(ResetWindowScroll);
}

Routes.js

import React from 'react';
import { Route, IndexRoute } from 'react-router';


import App from '../components/App';
import About from '../components/pages/About';
import Blog from '../components/pages/Blog'
import Index from '../components/Landing';
import NotFound from '../components/navigation/NotFound';
import ScrollIntoView from '../components/navigation/ScrollIntoView';


export default (
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route path="/about" component={About} />
<Route path="/blog" component={ScrollIntoView(Blog)} />
<Route path="*" component={NotFound} />
</Route>
);

上面的例子工作得很好,但如果你已经迁移到react-router-dom,那么你可以通过创建一个包装组件的HOC来简化上面的例子。

同样,你也可以很容易地将它包装在你的路由上(只需将componentDidMount方法更改为上面写的componentDidUpdate方法示例代码,以及用withRouter包装ScrollIntoView)。

容器/ ScrollIntoView.js

import { PureComponent, Fragment } from "react";


class ScrollIntoView extends PureComponent {
componentDidMount = () => window.scrollTo(0, 0);


render = () => this.props.children
}


export default ScrollIntoView;

组件/ Home.js

import React from "react";
import ScrollIntoView from "../containers/ScrollIntoView";


export default () => (
<ScrollIntoView>
<div className="container">
<p>
Sample Text
</p>
</div>
</ScrollIntoView>
);

我正在使用react-router ScrollToTop组件,该组件的代码在react-router文档中描述

https://reacttraining.com/react-router/web/guides/scroll-restoration/scroll-to-top

我在单个路由文件中更改代码,之后不需要在每个组件中更改代码。

示例代码-

步骤1 -创建ScrollToTop.js组件

import React, { Component } from 'react';
import { withRouter } from 'react-router';


class ScrollToTop extends Component {
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
window.scrollTo(0, 0)
}
}


render() {
return this.props.children
}
}


export default withRouter(ScrollToTop)

步骤2 -在App.js文件中,在<Router之后添加ScrollToTop Component

const App = () => (
<Router>
<ScrollToTop>
<App/>
</ScrollToTop>
</Router>
)

以上所有的方法对我都不起作用——不知道为什么,但是:

componentDidMount(){
document.getElementById('HEADER').scrollIntoView();
}

working,其中HEADER是HEADER元素的id

在反应路由有一个问题,如果我们重定向到新的路由,那么它不会自动带你到页面的顶部。

就连我也有同样的问题。

我只是将单行添加到组件中,它就像黄油一样工作。

componentDidMount() {
window.scrollTo(0, 0);
}

参考:反应训练

如果你在移动中这样做,至少在chrome中,你会在底部看到一个白色的条。

这发生在URL栏消失时。解决方案:

将height/min-height: 100%的css更改为height/min-height: 100年vh

谷歌开发人员文档

这段代码将导致滚动上的流畅的行为:

<div onClick={() => {
ReactDOM.findDOMNode(this.headerRef)
.scrollIntoView({behavior: "smooth"});
}}
className='go-up-button' >
</div>
你可以在scrollIntoView()中传递其他参数 可以使用以下语法:

element.scrollIntoView();
element.scrollIntoView(alignToTop); // Boolean parameter
element.scrollIntoView(scrollIntoViewOptions); // Object parameter
< p > alignToTop可选的 是布尔值:

If true, the top of the element will be aligned to the top of the visible area of the scrollable ancestor. Corresponds to scrollIntoViewOptions: {block: "start", inline: "nearest"}. This is the default value.
If false, the bottom of the element will be aligned to the bottom of the visible area of the scrollable ancestor. Corresponds to scrollIntoViewOptions: {block: "end", inline: "nearest"}.
< p > scrollIntoViewOptions可选的

*behavior* Optional
Defines the transition animation.
One of "auto", "instant", or "smooth". Defaults to "auto".
*block* Optional
One of "start", "center", "end", or "nearest". Defaults to "center".
*inline* Optional
One of "start", "center", "end", or "nearest". Defaults to "nearest".

更多细节可以在这里找到:MDN文档

我在一个组件上使用了类似的方法:

<div ref="scroller" style=\{\{height: 500, overflowX: "hidden", overflowY: "auto"}}>
//Content Here
</div>

然后在处理更新的函数中:

this.refs.scroller.scrollTop=0

所有的解决方案都谈论在componentDidMountcomponentDidUpdate上添加滚动,但使用DOM。

我做了所有这些,但都没用。

所以我找到了另一种适合我的方法。

< p >添加 componentDidUpdate() { window.scrollTo(0, 0) } 在头文件中,我的元素不在<Switch></Switch>元素中。

我还发现了一些ScrollRestoration的东西,但我现在很懒。现在我打算把它保留为“didupdate”;道路

以上答案目前对我来说都没用。事实证明,.scrollTo并不像.scrollIntoView那样广泛兼容。

在我们的App.js中,在componentWillMount()中添加了

    this.props.history.listen((location, action) => {
setTimeout(() => { document.getElementById('root').scrollIntoView({ behavior: "smooth" }) }, 777)
})
这是唯一适用于我们的解决方案。 root是我们的应用程序的ID。“平滑”行为并不适用于每个浏览器/设备。777的超时有点保守,但我们在每个页面上都加载了大量数据,所以通过测试,这是必要的。较短的237可能适用于大多数应用程序

以上答案目前对我来说都没用。事实证明,.scrollTo并不像.scrollIntoView那样广泛兼容。

在我们的App.js中,在componentWillMount()中添加了

this.props.history.listen((location, action) => {
setTimeout(() => { document.getElementById('root').scrollIntoView({ behavior: "smooth" }) }, 777)
})

这是唯一适用于我们的解决方案。root是我们应用的ID。“平滑”行为并不适用于每个浏览器/设备。777的超时有点保守,但我们在每个页面上都加载了大量数据,所以通过测试,这是必要的。更短的237可能适用于大多数应用程序。

对于那些使用钩子的人,下面的代码可以工作。

React.useEffect(() => {
window.scrollTo(0, 0);
}, []);

注意,你也可以直接导入useEffect: import { useEffect } from 'react'

我正在使用React Hooks,想要一些可重用的东西,但也想要一些我可以随时调用的东西(而不是仅仅在渲染之后)。

// utils.js
export const useScrollToTop = (initialScrollState = false) => {
const [scrollToTop, setScrollToTop] = useState(initialScrollState);


useEffect(() => {
if (scrollToTop) {
setScrollToTop(false);
try {
window.scroll({
top: 0,
left: 0,
behavior: 'smooth',
});
} catch (error) {
window.scrollTo(0, 0);
}
}
}, [scrollToTop, setScrollToTop]);


return setScrollToTop;
};

然后使用钩子你可以做:

import { useScrollToTop } from 'utils';


const MyPage = (props) => {
// initialise useScrollToTop with true in order to scroll on page load
const setScrollToTop = useScrollToTop(true);


...


return <div onClick={() => setScrollToTop(true)}>click me to scroll to top</div>
}

钩的解决方案:

  • 创建一个ScrollToTop钩子

import { useEffect } from "react";
import { withRouter } from "react-router-dom";


const ScrollToTop = ({ children, location: { pathname } }) => {
useEffect(() => {
window.scrollTo({
top: 0,
left: 0,
behavior: "smooth"
});
}, [pathname]);


return children || null;
};


export default withRouter(ScrollToTop);


  • 用它包装你的应用程序

<Router>
<ScrollToTop>
<App />
</ScrollToTop>
</Router>


文档:https://reacttraining.com/react-router/web/guides/scroll-restoration

在功能组件中使用钩子, 假设在结果props

中有更新时组件更新
import React, { useEffect } from 'react';


export const scrollTop = ({result}) => {
useEffect(() => {
window.scrollTo(0, 0);
}, [result])
}

我遇到了这个问题,与盖茨比建立一个网站,其链接是建立在Reach路由器的顶部。这似乎很奇怪,这是一个必须做出的修改,而不是默认的行为。

不管怎样,我尝试了上面的许多解决方案,唯一对我有效的是:

document.getElementById("WhateverIdYouWantToScrollTo").scrollIntoView()

我把它放在一个useEffect中,但你也可以很容易地把它放在componentDidMount中,或者以任何你想要的方式触发它。

不知道为什么是窗口。scrollTo(0,0)对我(和其他人)不起作用。

如果我假设您正在呈现一个章节,比如每页一本书,那么您所需要做的就是将此添加到代码中。这对我来说就像魔法一样有效。

    componentDidUpdate(prevProps) {
if (prevProps.currentChapter !== this.props.currentChapter) {
window.scrollTo(0, 0);
}
}

这样,你就不需要在被呈现的组件上创建一个引用。

如果所有人都想做一些简单的事情,这里有一个解决方案,对每个人都适用

添加这个迷你函数

scrollTop()
{
window.scrollTo({
top: 0,
behavior: "smooth"
});
}

从页脚调用函数,如下所示

<a className="scroll-to-top rounded" style=\{\{display: "inline"}} onClick={this.scrollTop}>TOP</a>

如果你想添加漂亮的样式,这里是CSS

.scroll-to-top {
position: fixed;
right: 1rem;
bottom: 1rem;
display: none;
width: 2.75rem;
height: 2.75rem;
text-align: center;
color: #fff;
background: rgba(90, 92, 105, 0.5);
line-height: 46px;
}

这就是我所做的:

useEffect(() => ref.current.scrollTo(0, 0));
const ref = useRef()


return(
<div ref={ref}>
...
</div>
)

没有什么对我有用,除了:

componentDidMount(){


$( document ).ready(function() {
window.scrollTo(0,0);
});
}

这对我很有用。

import React, { useEffect } from 'react';


useEffect(() => {
const body = document.querySelector('#root');


body.scrollIntoView({
behavior: 'smooth'
}, 500)


}, []);

功能组件;

import React, {useRef} from 'react';
function ScrollingExample (props) {
// create our ref
const refToTop = useRef();


return (
<h1 ref={refToTop}> I wanna be seen </h1>
// then add enough contents to show scroll on page
<a onClick={()=>{
setTimeout(() => { refToTop.current.scrollIntoView({ behavior: 'smooth' })}, 500)
}}>  Take me to the element <a>
);
}

我什么都试过了,但这是唯一有效的办法。

 useLayoutEffect(() => {
document.getElementById("someID").scrollTo(0, 0);
});

我在index.html页面上添加了一个事件侦听器,因为所有页面加载和重新加载都是通过它完成的。下面是代码片段。

// Event listener
addEventListener("load", function () {
setTimeout(hideURLbar, 0);
}, false);
  

function hideURLbar() {
window.scrollTo(0, 1);
}

点击后出现的页面,只需在其中写入即可。

  componentDidMount() {
window.scrollTo(0, 0);
}

我有一段时间也有同样的问题。添加窗口。scrollTo(0,0);到每个页面都是痛苦和冗余的。所以我添加了一个HOC,它将包装我所有的路由,它将留在BrowserRouter组件:

 <ScrollTop>
<Routes />
</ScrollTop>

在ScrollTopComponent内部,我们有以下内容:

import React, { useEffect } from "react";
import { useLocation } from "react-router-dom";


const ScrollTop = (props) => {
const { children } = props;


const location = useLocation();


useEffect(() => {
window.scrollTo(0, 0);
}, [location]);


return <main>{children}</main>;
};


export default ScrollTop;

看起来所有的useEffect例子都没有考虑到你可能想要通过状态改变来触发这个。

const [aStateVariable, setAStateVariable] = useState(false);


const handleClick = () => {
setAStateVariable(true);
}


useEffect(() => {
if(aStateVariable === true) {
window.scrollTo(0, 0)
}
}, [aStateVariable])

我在React 17.0中使用功能组件和窗口做SPA。滚动窗口。scrollTo和所有这些变体都不适合我。所以我用useRef钩子做了一个解决方案。我用Ref在组件的顶部创建了一个span标签然后使用Ref。current。scrollintoview ()

这里有一个简短的例子:

import React, { useEffect,useRef} from 'react';


export const ExampleComponent = () => {


const ref = useRef();


useEffect(() => {
ref.current.scrollIntoView()
}, []);


return(


<>
<span ref={ref}></span>
<YourCodeHere />
<MoreCode />
</>
< p >) } < / p >

功能性组件的解决方案-使用useEffect()钩子

 useEffect(() => {
window.history.scrollRestoration = 'manual';}, []);

这个解决方案既适用于功能组件,也适用于类基。

首先,我不喜欢每次重新渲染时滚动到顶部的想法,相反,我喜欢附加函数到特定的事件。

步骤#1:创建一个ScrollToTop函数

const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};

步骤2:在event对象上调用此函数,例如onClick

onRowClick={scrollToTop()}
// onClick={scrollToTop()}
// etc...

我已经尝试过@sledgeweight解决方案,但它并不适用于某些视图。但是添加setTimeout似乎可以完美地工作。以防有人遇到和我一样的问题。下面是我的代码。

import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'


const ScrollToTop = () => {
const { pathname } = useLocation()
useEffect(() => {
console.log(pathname)
/* settimeout make sure this run after components have rendered. This will help fixing bug for some views where scroll to top not working perfectly */
setTimeout(() => {
window.scrollTo({ top: 0, behavior: 'smooth' })
}, 0)
}, [pathname])
return null
}


export default ScrollToTop

在AppRouter.js中使用它

<Router>
<ScrollToTop/>
<App>
</Router>

平滑滚动到顶部。在钩子中,你可以在生命周期安装状态中使用此方法进行一次渲染

useEffect(() => {
window.scrollTo({top: 0, left: 0, behavior: 'smooth' });
}, [])

对于React v18+,我的建议是使用包装器组件,这将是最简单的执行方式。

步骤1:创建一个ScrollToTop组件(component/ScrollToTop.js)

import { useEffect } from "react";
import { useLocation } from "react-router-dom";


export function ScrollToTop() {
const { pathname } = useLocation();


useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);


return null;
}

步骤2:用它包装你的应用(index.js)

<React.StrictMode>
<BrowserRouter>
<ScrollToTop />
<App />
</BrowserRouter>
</React.StrictMode>

解释:每次路径名改变时,useEffect将被调用以将页面滚动到顶部。

useEffect(() => {
const body = document.querySelector('#root');


body.scrollIntoView({
behavior: 'smooth'
}, 500)


}, []);

这是查看顶部滚动页面的最佳解决方案

或者使用ref来跳转页面

    // a link jump to page react
const ref = useRef(null);


const handleClick = () => {
ref.current?.scrollIntoView({behavior: 'smooth'});
};


<button onClick={handleClick}>Scroll to element</button>
<div ref={ref}>Some content here</div>