your programing

resact.js로 렌더링한 후 페이지 맨 위로 스크롤합니다.

lovepro 2023. 4. 2. 12:23
반응형

resact.js로 렌더링한 후 페이지 맨 위로 스크롤합니다.

어떻게 풀어야 할지 모르는 문제가 있어요.리액션 컴포넌트에서는 데이터 목록이 길고 링크 수가 적습니다.이 링크 중 하나를 클릭하면 목록에 링크의 새로운 컬렉션을 입력하고 맨 위로 스크롤해야 합니다.

문제는 새 컬렉션을 렌더링한 후 맨 로 스크롤하려면 어떻게 해야 합니까?

'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;

드디어...사용:

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

편집: 리액트 v16.8+

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

초기 버전의 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

이런 게 필요할 거야ReactDom은 react.14를 위한 것입니다.그렇지 않으면 반응하세요.

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

React 16+용 업데이트(2019년 5월 11일)

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

리액트 라우팅에서는 새로운 루트로 리다이렉트해도 자동으로 페이지 맨 위로 이동하지 않는 문제가 있습니다.

나조차도 같은 문제를 안고 있었다.

부품에 한 줄만 추가했는데 버터처럼 작동했어요.

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

참조: 리액트 트레이닝

후크 솔루션:

  • 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

후크를 사용하고 있는 유저에게는, 다음의 코드가 유효합니다.

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

useEffect를 가져올 수도 있습니다.import { useEffect } from 'react'

이는 참조를 사용하여 처리할 수 있으며, 아마도 처리해야 합니다.

"...ReactDOM.findDOMName을 "회피 해치"로 사용할 수 있지만 캡슐화가 깨지고 거의 모든 경우에 React 모델 내에서 코드를 구조화할 수 있는 더 명확한 방법이 있으므로 권장하지 않습니다."

코드 예:

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

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

다음과 같이 라우터에서 실행할 수 있습니다.

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를 참조하십시오.

난 이거면 돼.

import React, { useEffect } from 'react';

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

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

}, []);

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 위의 할 수 HOC컴포넌트를 감싼다.

한 번, 마찬가지로 쉽게 할 수 만 하면 ).componentDidMount의 메서드componentDidUpdate및 랩핑 " " method method method method method method method method method 。ScrollIntoViewwithRouter를 참조해 주세요.

컨테이너/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>
);

이 솔루션은 기능 컴포넌트 및 클래스 베이스에서 동작합니다.

우선, 모든 리렌더에 Scroll to top을 붙이는 것은 싫고, 대신 특정 이벤트에 부가 기능을 붙이는 것이 좋습니다.

순서 1: ScrollToTop으로 기능 생성

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

이이 함수는 2: 이 함수로 호출합니다.event: ★onClick

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

리액트 라우터 문서에 설명된 코드인 리액트 라우터 ScrollToTop 컴포넌트를 사용하고 있습니다.

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 - 를 2 - App.js "ScrollToTop" 뒤에 합니다.<Router

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

모든 것이 간단한 것이라면, 여기에서는 모든 사람에게 효과가 있는 솔루션이 있습니다.

이 미니 기능을 추가하다

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

이것이 유일하게 기능한 것입니다(ES6 클래스 컴포넌트).

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

위의 모든 것이 나에게는 효과가 없었습니다.왜 그런지 모르겠지만:

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

HEADER는 헤더 요소의 ID입니다.

@sledgeweight 솔루션을 시도했지만 일부 뷰에서는 잘 작동하지 않습니다.그러나 set Timeout을 추가하는 것은 완벽하게 작동하는 것 같습니다.누군가 나와 같은 문제에 직면했을 때를 대비해서.아래는 제 코드입니다.

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>

기능 컴포넌트에서 후크를 사용하여 결과 소품에서 업데이트가 있을 때 컴포넌트가 업데이트된다고 가정합니다.

import React, { useEffect } from 'react';

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

클릭 후에 표시되는 페이지는, 거기에 기입하기만 하면 됩니다.

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

맨 위로 부드럽게 스크롤합니다.후크에서는 이 방법을 라이프 사이클 마운트 상태 내에서 한 번 렌더링할 수 있습니다.

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

모든 useEffect 예제는 고려되지 않는 것으로 보입니다.상태 변경으로 트리거할 수 있습니다.

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

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

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

다 해봤지만 이것밖에 안 먹혔어요.

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

제가 한 일은 다음과 같습니다.

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

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

기능 컴포넌트와 window.scroll, window.scrollTo를 사용하여 React 17.0에서 SPA를 실행 중이었는데 이 모든 변종에서 문제가 발생하였습니다.그래서 저는 useRef 훅을 사용하여 해결책을 만들었습니다.Ref를 사용하여 컴포넌트 상단에 스판 태그를 만들고 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 />
</>

) }

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

나는 Reach Router 위에 링크가 구축되어 있는 Gatsby와 사이트를 구축하면서 이 문제에 부딪쳤다.이것이 기본 동작보다는 수정되어야 하는 것이 이상하다고 생각됩니다.

어쨌든, 저는 위의 많은 솔루션을 시도해 보았습니다만, 실제로 효과가 있었던 것은 다음과 같습니다.

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

useEffect에 넣었지만 componentDidMount에 넣거나 원하는 방식으로 트리거할 수 있습니다.

window.scrollTo(0, 0)가 왜 다른 사람에게 작동하지 않는지 모르겠습니다.

저도 한동안 같은 문제를 안고 있었어요.모든 페이지에 window.scrollTo(0, 0)를 추가하는 것은 번거롭고 장황합니다.따라서 모든 루트를 랩핑하여 BrowserRouter 컴포넌트 내에 머무르는 HOC를 추가했습니다.

 <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() 후크 사용

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

React v18+의 경우 래퍼 컴포넌트를 사용하는 것이 가장 쉬운 실행 방법입니다.

순서 1: ScrollToTop 컴포넌트(컴포넌트/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가 호출되어 페이지가 맨 위로 스크롤됩니다.

적어도 크롬을 사용하는 모바일용이라면 하단에 흰색 막대가 표시됩니다.

이 문제는 URL 표시줄이 사라지면 발생합니다.솔루션:

높이/최소 높이:100%를 높이/최소 높이:100vh로 변경합니다.

Google 개발자 문서

위의 답변 중 어느 것도 현재 나에게는 효과가 없습니다. 보니, ★★★★★★★★★★★★★★★★★★..scrollTo할 수 .scrollIntoView.

App.js에서는componentWillMount()추가했습니다

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

이것은 우리에게 보편적으로 기능하는 유일한 솔루션입니다.root은 우리 앱의 ID입니다."스무스" 동작은 모든 브라우저/디바이스에서 동작하는 것은 아닙니다.777 타임아웃은 다소 보수적이지만 모든 페이지에 많은 데이터를 로드하기 때문에 테스트를 통해 이것이 필요했습니다.대부분의 어플리케이션에서는 짧은 237이 유효할 수 있습니다.

언급URL : https://stackoverflow.com/questions/33188994/scroll-to-the-top-of-the-page-after-render-in-react-js

반응형