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

时间:2015-10-17 16:37:29

标签: scroll reactjs render

我有一个问题,我没有想法,如何解决。 在我的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;

34 个答案:

答案 0 :(得分:190)

最后..我用过:

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

答案 1 :(得分:48)

由于原始解决方案是为 react 的早期版本提供的,因此这是一个更新:

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

答案 2 :(得分:36)

你可以使用这样的东西。 ReactDom用于反应.14。只是反应。

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

更新5/11/2019以获取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) {
      const that = this
      setTimeout(() => {
        that.childDiv.current.scrollIntoView({ behavior: 'smooth' })
      }, 500)
    }
  }

答案 3 :(得分:13)

这可能,也可能应该使用refs来处理:

  

&#34; ...你可以使用ReactDOM.findDOMNode作为&#34;逃生舱&#34;但是我们不推荐它,因为它破坏了封装,几乎在所有情况下,都有更清晰的方法在React模型中构建代码。&#34;

示例代码:

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

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

答案 4 :(得分:11)

在React Routing中存在一个问题,即如果我们重定向到新路线,那么它不会自动将您带到页面顶部。

即使我确实遇到了同样的问题。

我刚刚将单行添加到我的组件中,它就像黄油一样。

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

参考:react training

答案 5 :(得分:9)

您可以在路由器中执行此操作:

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 link

答案 6 :(得分:6)

这是另一种方法,允许您选择希望窗口滚动位置重置为哪个已安装的组件,而不会大量复制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方法示例代码,并将ScrollIntoView包裹在{ {1}})。

<强>容器/ ScrollIntoView.js

withRouter

<强>组件/ Home.js

import { PureComponent, Fragment } from "react";

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

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

export default ScrollIntoView;

答案 7 :(得分:6)

我正在使用react-router ScrollToTop组件,其中的代码在react-router docs中描述

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

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

示例代码 -

第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组件

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

答案 8 :(得分:5)

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

添加此迷你功能

--max_fetch_bytes 2147483000
--min_fetch_bytes 2147483000
--max_poll_records 2147483000
--max_partition_fetch_bytes 2147483000
--enable_auto_commit false
--fetch_max_wait 900000

从页面页脚中调用以下函数

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

如果您想添加漂亮的样式,这里是css

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

答案 9 :(得分:5)

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

new_tcp_check = ~(~old_tcp_check +  ~old_val + new_val)

答案 10 :(得分:4)

看起来所有 useEffect 示例都没有考虑到您可能希望通过状态更改来触发它。

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

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

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

答案 11 :(得分:2)

如果您要针对移动进行此操作,至少使用chrome,则会在底部看到一个白色的条。

URL栏消失时,会发生这种情况。解决方案:

  

将高度/最小高度的css: 100%更改为高度/最小高度: 100vh

Google Developer Docs

答案 12 :(得分:2)

点击后显示的页面,只需将其写入。

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

答案 13 :(得分:2)

我正在使用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>
}

答案 14 :(得分:1)

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

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

答案 15 :(得分:1)

我在 React 17.0 中使用功能组件和 window.scroll、window.scrollTo 和所有这些变体做 SPA 对我不起作用。所以我使用 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 />
</>

) }

答案 16 :(得分:1)

我有一段时间遇到同样的问题。将 window.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;

答案 17 :(得分:1)

我尝试了一切,但这是唯一有效的方法。

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

答案 18 :(得分:1)

对于功能组件;

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>
);
}

答案 19 :(得分:1)

您可以使用,这对我有用。

import React, { useEffect } from 'react';

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

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

}, []);

答案 20 :(得分:1)

这就是我所做的:

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

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

答案 21 :(得分:1)

挂钩解决方案

  • 创建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

答案 22 :(得分:1)

在功能组件中使用挂钩, 假设结果道具有更新时,组件也会更新

import React, { useEffect } from 'react';

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

答案 23 :(得分:1)

以上所有内容对我都不起作用 - 不知道为什么,但是:

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

工作,其中HEADER是我的标题元素的ID

答案 24 :(得分:0)

如果我假设您每页要渲染一章,例如一本书,那么您要做的就是将其添加到代码中。这对我来说就像魔术一样。

>         [WebMethod(EnableSession = true)]
>   
>         public Transaction<Employee> GetEmployee(string Fname, string Lname, int eid)
>         {
>             
>             return _service.GetEmployee(Fname, Lname, apartmentTypeId, eid);
>         }

这样,您无需在要渲染的组件上创建引用。

答案 25 :(得分:0)

我遇到了这个问题,它与Gatsby一起构建了一个站点,该站点的链接建立在Reach Router的顶部。奇怪的是,这是必须进行的修改,而不是默认的行为。

无论如何,我尝试了上面的许多解决方案,唯一对我有用的解决方案是:

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

我将其放在useEffect中,但您也可以将其轻松放入componentDidMount或以其他任何想要的方式触发它。

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

答案 26 :(得分:0)

对于使用钩子的人,以下代码将起作用。

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

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

答案 27 :(得分:0)

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

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

答案 28 :(得分:0)

以上答案均不适用于我。事实证明,.scrollTo不如.scrollIntoView广泛兼容。

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

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

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

答案 29 :(得分:0)

所有解决方案都讨论在componentDidMountcomponentDidUpdate上添加滚动条,但要添加DOM。

我做了所有的事情,但没有成功。

所以,想出了一些对我来说很好的方法。

  

已添加   componentDidUpdate() { window.scrollTo(0, 0) }   在标题上,该地雷不在<Switch></Switch>元素之内。只需在应用程序中免费。有效。

我也发现了一些ScrollRestoration的东西,但是现在我很懒。现在,将其保留为“ DidUpdate”方式。

希望有帮助!

安全

答案 30 :(得分:0)

此代码将导致滚动上的平滑行为

<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

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"}.

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 docs

答案 31 :(得分:0)

此解决方案适用于功能组件和类库。

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

第 1 步:创建一个 ScrollToTop 函数

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

第 2 步:在 event 上调用此函数,例如 onClick

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

答案 32 :(得分:-1)

除了对我没有任何帮助

componentDidMount(){

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

答案 33 :(得分:-1)

以上答案均不适用于我。事实证明,.scrollTo不如.scrollIntoView广泛兼容。

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

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

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