Прокрутите до верхней части страницы после рендера вact.js

82

У меня проблема, у меня нет идей, как решить. В моем компоненте реакции я показываю длинный список данных и несколько ссылок внизу. После нажатия на любую из этих ссылок я заполняю список новой коллекцией ссылок и должен прокручивать вверх.

Проблема заключается в следующем: как прокручивается верхняя после визуализация новой коллекции?

'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;
Теги:
scroll
render

15 ответов

40
Лучший ответ

Так как оригинальное решение было предоставлено для очень ранней версии реакции, вот обновление:

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
  • 0
    this.getDOMNode === undefined
  • 1
    @DaveLunny, ты можешь быть на15? попробуйте импортировать ReactDOM и выполнить ReactDOM.findDOMNode(this).scrollTop = 0
Показать ещё 2 комментария
151

Наконец, я использовал:

componentDidMount() {
  window.scrollTo(0, 0)
}
  • 2
    Это единственное решение, которое сработало для меня. Также пробовал: ReactDOM.findDOMNode (this) .scrollTop = 0 и componentDidMount () {this._div.scrollTop = 0} render () {return <div ref = {(ref) => this._div = ref} />}
  • 0
    Согласно W3Schools, это решение в настоящее время поддерживается всеми браузерами. Также библиотека ReactDOM устарела в будущих версиях React.
Показать ещё 8 комментариев
30

Вы можете использовать что-то вроде этого. ReactDom для реагирования .14. Просто в противном случае.

    componentDidUpdate = () => { ReactDom.findDOMNode(this).scrollIntoView(); }
  • 0
    Из всех предложений на этой странице, это единственный, который работает для меня.
  • 0
    Примечание: если componentDidUpdate не работает для вас, componentDidMount является другой альтернативой.
Показать ещё 1 комментарий
12

Это можно и, вероятно, следует обрабатывать с помощью refs:

"... вы можете использовать ReactDOM.findDOMNode как" escape-hatch ", но мы не рекомендуем его, так как он прерывает инкапсуляцию и почти в каждом случае имеет более четкий способ структурирования вашего кода в модели React."

Пример кода:

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

    render() {
        return <div ref={(ref) => this._div = ref} />
    }
}
  • 0
    Это прекрасно работает. Благодарю. Чтобы было ясно, я поместил <div ref={(ref) => this._div = ref} /> в самый первый <div> моего оператора рендеринга. Остальная часть моего рендера остается точно такой же.
  • 0
    Если вы используете стилевые компоненты, вам нужно будет использовать «innerRef» вместо «ref». Отличное решение
Показать ещё 2 комментария
8

Вы можете сделать это в маршрутизаторе следующим образом:

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

  • 0
    элегантное решение, которое требует лишь небольшого изменения кода в маршрутизаторе, а не того, чтобы каждый компонент обрабатывал его сам. <3
  • 0
    К сожалению, onUpdate срабатывает с каждым новым маршрутомParam, маршрутизируемым по данному маршруту. Так, если, например, у вас есть страница с кучей изображений, и если вы можете развернуть изображение в модальном режиме при нажатии, изменив маршрут на /somePage/:imgId , он прокрутится вверх :(. Любой способ «контролировать» стоит ли запускать событие onUpdate на определенных маршрутах / параметрах?
Показать ещё 1 комментарий
6

В React Routing существует проблема, заключающаяся в том, что если мы перенаправим на новый маршрут, то он автоматически не приведет вас к началу страницы.

Даже у меня была такая же проблема.

Я просто добавил одну строку в свой компонент, и он работал как масло.

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

Обратитесь: отреагируйте обучение

5

Я использую компонент ScrollToTop для взаимодействия с ретранслятором, код которого описан в документах реагирования-маршрутизатора

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 добавьте компонент ScrollToTop после <Router

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

Здесь еще один подход, который позволяет вам выбрать, какие смонтированные компоненты вы хотите, чтобы положение прокрутки окна было сброшено без массового дублирования ComponentDidUpdate/ComponentDidMount.

В приведенном ниже примере выполняется перенос компонента Blog с помощью ScrollIntoView(), так что если маршрут изменяется при установке компонента 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, то вы можете упростить это, создав команду render, которая обертывает компонент.

Еще раз, вы также можете так же легко обернуть его на маршрутах (просто изменить componentDidMount метод к componentDidUpdate метод примера кода, написанного выше, а также упаковка ScrollIntoView с withRouter).

Рабочий пример: https://codesandbox.io/s/qq4x5x43k9 (только щелчок на дому обновляет положение окна)

контейнеры/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>
);
  • 0
    ScrollIntoView.js дает мне следующую ошибку «неиспользуемое выражение, ожидание назначения или вызова функции»
  • 0
    @ EX0MAK3R - Обновлен ответ.
4

Это единственное, что сработало для меня (с компонентом класса ES6):

componentDidMount() {
  ReactDOM.findDOMNode(this).scrollIntoView();
}
  • 0
    и для меня это единственный рабочий ответ
2

Вы можете просто использовать это:

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

Если вы делаете это для мобильных устройств, по крайней мере, с хромом, вы увидите белую полосу внизу.

Это происходит, когда строка URL исчезает. Решение:

Измените CSS для высоты/минимальной высоты: 100% на высоту/минимальной высоты: 100vh.

Документы для разработчиков Google

1

Все вышесказанное не помогло мне - не знаю почему, но:

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

работал, где HEADER является идентификатором моего элемента заголовка

0

Все решения говорят о добавлении прокрутки на componentDidMount или componentDidUpdate но с DOM.

Я сделал все это и не работал.

Итак, выяснил какой-то другой способ, который отлично подходит для меня.

Добавлен componentDidUpdate() { window.scrollTo(0, 0) } в заголовке, что моя из-за элемента <Switch></Switch>. Просто бесплатно в приложении. Работает.

Я также нашел кое-что о ScrollRestoration, но теперь я ленив. И на данный момент держим это "DidUpdate".

Надеюсь, поможет!

быть в безопасности

0

Что-то вроде этого работало для меня на компоненте:

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

Затем в любой функции, связанной с обновлениями:

this.refs.scroller.scrollTop=0
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 документы

Ещё вопросы

Сообщество Overcoder
Наверх
Меню