React Router Link 리로딩 페이지 : 외부 이벤트와 충돌

Sep 17 2020

내 앱에서 페이지 전환을 처리하기 위해 React Router의 Link 구성 요소를 사용하고 있습니다.

내 앱은 문서 수준의 링크에 대한 이벤트를 정의하는 일부 스크립트 (즉, Google 태그 관리자)가있는 외부 웹 페이지에 포함되어 있습니다.

이로 인해 링크 이벤트와 충돌이 발생합니다. 링크를 클릭하면 페이지가 항상 다시로드됩니다.

운없이 onClick 콜백으로 Link 구성 요소에서 전파를 중지하려고했습니다. <Link onClick={(e) => { e.stopPropagation(); }} [...]>...</Link>

링크 이벤트도 문서 수준에서 정의되어 있으므로 외부 이벤트를 중지하는 방법을 모르겠습니다.

이것에 대한 단서가 있습니까?

감사합니다 !

답변

1 MathieuRios Oct 15 2020 at 15:00

내 앱 중 하나에서 비슷한 문제에 직면했고 해결책은 가능한 react-router <Link /> component경우 사용하지 않는 것이라고 생각합니다 .

<Link />구성 요소 를 사용하는 대신 다음에서 withRouter()제공 하는 HOC를 사용했습니다 react-router.

당신이 쓴 것 :

Class MyComponent extends React.Component{
  <Link onClick={(e) => { e.stopPropagation(); }} [...]>
    ...
  </Link>
}

export default MyComponent;

다음으로 대체 가능 :

Class MyComponent extends React.Component{

  navigate = (event, location) => {
    event.preventDefault();
    this.props.history.push(location);
  }

  <a onClick={(e, href) => { this.navigate(e, href) }} [...]>
    ...
  </a>
}

export default withRouter(MyComponent);

이렇게하면 링크가 문서 수준에서 다른 이벤트를 포착하고 <Link />구성 요소 와 동일한 결과를 얻지 못합니다.

2 LionelRowe Sep 21 2020 at 14:42

업데이트 : .NET Framework에서 전체 앱을 렌더링하지 않고이를 수행하는 간단한 방법은없는 것 같습니다 iframe.

그래도 괜찮다면 충분히 쉽습니다 ( 반응 구성 요소의 iframe 콘텐츠를 설정하는 방법에서 가져옴 ).

const Frame = ({ children }) => {
    const [ref, setRef] = useState(null)
    const mountNode = ref?.contentWindow.document.body

    return (
        <iframe title="iframe" ref={setRef}>
            {mountNode && ReactDOM.createPortal(children, mountNode)}
        </iframe>
    )
}

그런 다음 기본 앱을 Frame구성 요소 의 하위로 래핑합니다 . iframe을 둘러싼 div 클릭 캡처에iframe 자세히 설명 된대로 내부의 클릭 은 상위 창으로 버블 링되지 않습니다 .

여기의 데모 CodeSandbox을 이 방법을 보여주는.


아래의 원래 (작동하지 않는) 답변

온 App또는 Router구성 요소 :

const blockClicks = useCallback((e) => {
    const { target } = e
    const { nodeName, href } = target
    if (
        target.closest('#root-id') &&
        nodeName === 'A' &&
        href &&
        (/^https?:\/\//.test(!href) ||
        href.startsWith(window.location.origin)
    )) {
        // amend logic specific to your use case
        // - we want to avoid blocking irrelevant clicks
        e.stopPropagation()
    }
})

useEffect(() => {
    document.addEventListener('click', blockClicks, true)

    return () =>
        document.removeEventListener('click', blockClicks, true)
})