Programing

리액터-루터와 함께 앵커 사용

c10106 2022. 3. 13. 10:10
반응형

리액터-루터와 함께 앵커 사용

리액션 라우터를 사용하고 특정 페이지의 특정 위치로 링크를 이동시키는 방법(예:/home-page#section-three)

세부 정보:

나는 사용하고 있다react-router내 리액트 앱에서.

페이지 특정 부분에 연결해야 하는 사이트 전체 탐색 모음을 가지고 있다./home-page#section-three.

그러니 설사 당신이 명령한다 해도/blog이 링크를 클릭하면 홈 페이지가 로드되고 섹션 3이 보기로 스크롤된다.이것이 바로 표준이다.<a href="/home-page#section-three>효과가 있을 거야

참고: 리액션 라우터의 작성자는 명시적인 답변을 하지 않았다.그들은 그것이 진행 중이고, 그 동안 다른 사람들의 대답을 사용한다.나는 지배적인 질문이 나올 때까지 이 문제를 계속 진행과 가능한 해결책으로 업데이트 할 수 있도록 최선을 다할 것이다.

연구:


리액터러터와 함께 일반 앵커 링크를 사용하는 방법

이 질문은 2015년부터입니다 (그래서 10년 전 반응 시간).가장 많이 인용된 대답은HistoryLocation대신에HashLocation. 기본적으로 해시 조각이 아닌 창 내역에 위치를 저장하는 것을 의미한다.

나쁜 소식은...HistoryLocation(2016년에 대부분의 튜토리얼과 문서들이 말하는 것)을 사용해도 앵커 태그는 여전히 작동하지 않는다.


https://github.com/ReactTraining/react-router/issues/394

앵커와 리액트라우터를 연결하는 방법에 대한 리액트 트레이닝의 스레드.이것은 확답이 아니다.제안된 대부분의 답변이 최신 버전이 아니므로 주의하십시오(예: "해시" 프로펠러 사용).<Link>)


React Router Hash Link는 나에게 효과가 있으며 설치 및 구현이 쉽다.

$ npm install --save react-router-hash-link

구성 요소.js에서 연결로 가져오기:

import { HashLink as Link } from 'react-router-hash-link';

그리고 닻을 사용하는 대신에<a>사용하다<Link> :

<Link to="home-page#section-three">Section three</Link>

참고: 사용하였다HashRouter대신에Router:

여기 내가 찾은 한 가지 해결책(2016년 10월)이 있다.크로스 브라우저 호환(Internet Explorer, Firefox, Chrome, 모바일 Safari 및 Safari에서 테스트됨)

다음을 제공할 수 있다.onUpdate라우터에 대한 속성.이것은 경로가 업데이트될 때마다 불린다.이 솔루션은 onUpdate 속성을 사용하여 해시와 일치하는 DOM 요소가 있는지 확인한 후 경로 전환이 완료된 후 해당 요소로 스크롤한다.

hashHistory가 아닌 브라우저History를 사용해야 한다.

해시 링크 #394의 "Rrafracs"에 의한 답이다.

정의한 위치에 이 코드 추가<Router>:

import React from 'react';
import { render } from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';

const routes = (
  // your routes
);

function hashLinkScroll() {
  const { hash } = window.location;
  if (hash !== '') {
    // Push onto callback queue so it runs after the DOM is updated,
    // this is required when navigating from a different page so that
    // the element is rendered on the page before trying to getElementById.
    setTimeout(() => {
      const id = hash.replace('#', '');
      const element = document.getElementById(id);
      if (element) element.scrollIntoView();
    }, 0);
  }
}

render(
  <Router
    history={browserHistory}
    routes={routes}
    onUpdate={hashLinkScroll}
  />,
  document.getElementById('root')
)

만약 당신이 게을러지고 있고 그 코드를 복사하고 싶지 않다면, 당신은 단지 당신을 위해 그 기능을 정의하는 Anchoch를 사용할 수 있다.https://github.com/adjohnson916/anchorate

이 솔루션은 리액터 v5와 함께 작동함

import React, { useEffect } from 'react'
import { Route, Switch, useLocation } from 'react-router-dom'

export default function App() {
  const { pathname, hash, key } = useLocation();

  useEffect(() => {
    // if not a hash link, scroll to top
    if (hash === '') {
      window.scrollTo(0, 0);
    }
    // else scroll to id
    else {
      setTimeout(() => {
        const id = hash.replace('#', '');
        const element = document.getElementById(id);
        if (element) {
          element.scrollIntoView();
        }
      }, 0);
    }
  }, [pathname, hash, key]); // do this on route change

  return (
      <Switch>
        <Route exact path="/" component={Home} />
        .
        .
      </Switch>
  )
}

구성 요소에서

<Link to="/#home"> Home </Link>

여기에 구독이나 타사 패키지가 필요하지 않은 간단한 솔루션이 있다.와 잘 어울려야 한다.react-router@3 그 이상 그 이상.react-router-dom.

작업 예: https://fglet.codesandbox.io/

소스(불행히도 현재 편집기 내에서 작동하지 않음):

단순 반응 앵커 편집


#스크롤핸들러 후크 예

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

const ScrollHandler = ({ location, children }) => {
  useEffect(
    () => {
      const element = document.getElementById(location.hash.replace("#", ""));

      setTimeout(() => {
        window.scrollTo({
          behavior: element ? "smooth" : "auto",
          top: element ? element.offsetTop : 0
        });
      }, 100);
    }, [location]);
  );

  return children;
};

ScrollHandler.propTypes = {
  children: PropTypes.node.isRequired,
  location: PropTypes.shape({
    hash: PropTypes.string,
  }).isRequired
};

export default withRouter(ScrollHandler);

#스크롤핸들러 클래스 예

import { PureComponent } from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router-dom";

class ScrollHandler extends PureComponent {
  componentDidMount = () => this.handleScroll();

  componentDidUpdate = prevProps => {
    const { location: { pathname, hash } } = this.props;
    if (
      pathname !== prevProps.location.pathname ||
      hash !== prevProps.location.hash
    ) {
      this.handleScroll();
    }
  };

  handleScroll = () => {
    const { location: { hash } } = this.props;
    const element = document.getElementById(hash.replace("#", ""));

    setTimeout(() => {
      window.scrollTo({
        behavior: element ? "smooth" : "auto",
        top: element ? element.offsetTop : 0
      });
    }, 100);
  };

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

ScrollHandler.propTypes = {
  children: PropTypes.node.isRequired,
  location: PropTypes.shape({
    hash: PropTypes.string,
    pathname: PropTypes.string,
  })
};

export default withRouter(ScrollHandler);

로컬 스크롤에 반응 라우터를 사용하지 마십시오.

document.getElementById('myElementSomewhere').scrollIntoView() 

Don P의 답변에 대한 문제는 때때로 해당 섹션이 비동기 동작에 의존하는 경우 ID가 있는 요소가 여전히 렌더링되거나 로드된다는 것이다.다음 기능은 id로 요소를 찾아 탐색한 후 최대 50번의 재시도에 도달할 때까지 100ms마다 재시도한다.

scrollToLocation = () => {
  const { hash } = window.location;
  if (hash !== '') {
    let retries = 0;
    const id = hash.replace('#', '');
    const scroll = () => {
      retries += 0;
      if (retries > 50) return;
      const element = document.getElementById(id);
      if (element) {
        setTimeout(() => element.scrollIntoView(), 0);
      } else {
        setTimeout(scroll, 100);
      }
    };
    scroll();
  }
}

Don P의 솔루션(위 참조)을 에 적응시켰다.react-router4 (2019년 1월)이 없기 때문에onUpdate을 떠받치다.<Router>더 이상

import React from 'react';
import * as ReactDOM from 'react-dom';
import { Router, Route } from 'react-router';
import { createBrowserHistory } from 'history';

const browserHistory = createBrowserHistory();

browserHistory.listen(location => {
    const { hash } = location;
    if (hash !== '') {
        // Push onto callback queue so it runs after the DOM is updated,
        // this is required when navigating from a different page so that
        // the element is rendered on the page before trying to getElementById.
        setTimeout(
            () => {
                const id = hash.replace('#', '');
                const element = document.getElementById(id);
                if (element) {
                    element.scrollIntoView();
                }
            },
            0
        );
    }
});

ReactDOM.render(
  <Router history={browserHistory}>
      // insert your routes here...
  />,
  document.getElementById('root')
)
<Link to='/homepage#faq-1'>Question 1</Link>
useEffect(() => {
    const hash = props.history.location.hash
    if (hash && document.getElementById(hash.substr(1))) {
        // Check if there is a hash and if an element with that id exists
        document.getElementById(hash.substr(1)).scrollIntoView({behavior: "smooth"})
    }
}, [props.history.location.hash]) // Fires when component mounts and every time hash changes

간단한 페이지 내 네비게이션의 경우 페이지 초기화를 처리하지는 않지만 이와 같은 내용을 추가할 수 있다.

// handle back/fwd buttons
function hashHandler() {
  const id = window.location.hash.slice(1) // remove leading '#'
  const el = document.getElementById(id)
  if (el) {
    el.scrollIntoView()
  }
}
window.addEventListener('hashchange', hashHandler, false)

대안: react-resignchor https://www.npmjs.com/package/react-scrollchor

react-scrollchor: 부드러운 애니메이션으로 #hash 링크로 스크롤할 수 있는 React 구성 요소.Scrollchor는 Scroll과 Anchor를 혼합한 것이다.

참고: 리액트라우터를 사용하지 않음

참조URL: https://stackoverflow.com/questions/40280369/use-anchors-with-react-router

반응형