React Router Link 리로딩 페이지 : 외부 이벤트와 충돌
내 앱에서 페이지 전환을 처리하기 위해 React Router의 Link 구성 요소를 사용하고 있습니다.
내 앱은 문서 수준의 링크에 대한 이벤트를 정의하는 일부 스크립트 (즉, Google 태그 관리자)가있는 외부 웹 페이지에 포함되어 있습니다.
이로 인해 링크 이벤트와 충돌이 발생합니다. 링크를 클릭하면 페이지가 항상 다시로드됩니다.
운없이 onClick 콜백으로 Link 구성 요소에서 전파를 중지하려고했습니다. <Link onClick={(e) => { e.stopPropagation(); }} [...]>...</Link>
링크 이벤트도 문서 수준에서 정의되어 있으므로 외부 이벤트를 중지하는 방법을 모르겠습니다.
이것에 대한 단서가 있습니까?
감사합니다 !
답변
내 앱 중 하나에서 비슷한 문제에 직면했고 해결책은 가능한 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 />구성 요소 와 동일한 결과를 얻지 못합니다.
업데이트 : .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)
})