검색 기록에 따라 비즈니스 로직을 구현해야합니다.
내가 원하는 것은 다음과 같습니다.
reactRouter.onUrlChange(url => {
this.history.push(url);
});
URL이 업데이트 될 때 react-router에서 콜백을받는 방법이 있습니까?
검색 기록에 따라 비즈니스 로직을 구현해야합니다.
내가 원하는 것은 다음과 같습니다.
reactRouter.onUrlChange(url => {
this.history.push(url);
});
URL이 업데이트 될 때 react-router에서 콜백을받는 방법이 있습니까?
답변:
history.listen()
경로 변경을 감지하려고 할 때 기능 을 사용할 수 있습니다 . 을 사용 react-router v4
하고 있다고 생각하면 컴포넌트를 withRouter
HOC로 감싸서 history
소품에 액세스하십시오 .
history.listen()
unlisten
함수를 반환합니다 . 당신 unregister
은 듣기에서 이것을 사용할 것 입니다.
다음과 같이 경로를 구성 할 수 있습니다.
index.js
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Route exact path="/" Component={...} />
<Route exact path="/Home" Component={...} />
</AppContainer>
</BrowserRouter>,
document.getElementById('root')
);
그런 다음 AppContainer.js에서
class App extends Component {
componentWillMount() {
this.unlisten = this.props.history.listen((location, action) => {
console.log("on route change");
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<div>{this.props.children}</div>
);
}
}
export default withRouter(App);
역사 문서에서 :
다음을 사용하여 현재 위치의 변경 사항을 수신 할 수 있습니다
history.listen
.
history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) })
위치 개체는 다음을 포함하여 window.location 인터페이스의 하위 집합을 구현합니다.
**location.pathname** - The path of the URL **location.search** - The URL query string **location.hash** - The URL hash fragment
위치에는 다음 속성도있을 수 있습니다.
location.state -URL에 상주하지 않는이 위치에 대한 일부 추가 상태 (
createBrowserHistory
및 에서 지원됨createMemoryHistory
)
location.key
-이 위치를 나타내는 고유 한 문자열 (createBrowserHistory
및createMemoryHistory
)작업은
PUSH, REPLACE, or POP
사용자가 현재 URL에 도달 한 방법 에 따라 다릅니다.
react-router v3를 사용하는 경우 위에서 언급 한대로 패키지 history.listen()
에서 사용 history
하거나 사용할 수도 있습니다.browserHistory.listen()
다음과 같은 경로를 구성하고 사용할 수 있습니다.
import {browserHistory} from 'react-router';
class App extends React.Component {
componentDidMount() {
this.unlisten = browserHistory.listen( location => {
console.log('route changes');
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<Route path="/" onChange={yourHandler} component={AppContainer}>
<IndexRoute component={StaticContainer} />
<Route path="/a" component={ContainerA} />
<Route path="/b" component={ContainerB} />
</Route>
)
}
}
react-router v4
"
withRouter
history.listen()
를 withRouter
이미 업데이트 할 때 왜 사용 합니까? nextProps.location.href === this.props.location.href
in 의 간단한 비교를 통해 componentWillUpdate
변경된 경우 수행해야하는 작업을 수행 할 수 있습니다.
React Router 5.1 업데이트.
import React from 'react';
import { useLocation, Switch } from 'react-router-dom';
const App = () => {
const location = useLocation();
React.useEffect(() => {
console.log('Location changed');
}, [location]);
return (
<Switch>
{/* Routes go here */}
</Switch>
);
};
history
객체를 전역 적으로 듣고 싶다면 직접 만들어서 Router
. 그런 다음 해당 listen()
방법으로 들을 수 있습니다 .
// Use Router from react-router, not BrowserRouter.
import { Router } from 'react-router';
// Create history object.
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
// Listen to history changes.
// You can unlisten by calling the constant (`unlisten()`).
const unlisten = history.listen((location, action) => {
console.log(action, location.pathname, location.state);
});
// Pass history to Router.
<Router history={history}>
...
</Router>
히스토리 객체를 모듈로 생성하는 것이 더 좋으므로 필요할 수있는 모든 곳에서 쉽게 가져올 수 있습니다 (예 : import history from './history';
react-router v6
다가오는 v6 에서는 useLocation
및 useEffect
후크 를 결합하여 수행 할 수 있습니다.
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
const location = useLocation()
React.useEffect(() => {
// runs on location, i.e. route, change
console.log('handle route change here', location)
}, [location])
...
}
편리한 재사용을 위해 사용자 지정 useLocationChange
후크 에서이 작업을 수행 할 수 있습니다.
// runs action(location) on location, i.e. route, change
const useLocationChange = (action) => {
const location = useLocation()
React.useEffect(() => { action(location) }, [location])
}
const MyComponent1 = () => {
useLocationChange((location) => {
console.log('handle route change here', location)
})
...
}
const MyComponent2 = () => {
useLocationChange((location) => {
console.log('and also here', location)
})
...
}
변경시 이전 경로도 확인해야하는 경우 usePrevious
후크 와 결합 할 수 있습니다.
const usePrevious(value) {
const ref = React.useRef()
React.useEffect(() => { ref.current = value })
return ref.current
}
const useLocationChange = (action) => {
const location = useLocation()
const prevLocation = usePrevious(location)
React.useEffect(() => {
action(location, prevLocation)
}, [location])
}
const MyComponent1 = () => {
useLocationChange((location, prevLocation) => {
console.log('changed from', prevLocation, 'to', location)
})
...
}
위의 모든 것이 마운트되는 첫 번째 클라이언트 경로와 후속 변경에서 발생한다는 점에 유의하는 것이 중요 합니다. 이것이 문제라면 후자의 예를 사용 prevLocation
하고 어떤 일을하기 전에 a 가 존재 하는지 확인하십시오 .
location
여기서 명확히하기 위해 브라우저 위치가 있으므로 모든 구성 요소에서 동일하며 그 의미에서 항상 정확합니다. 다른 구성 요소에서 후크를 사용하면 위치가 변경 될 때 모두 동일한 값을 받게됩니다. 나는 그들이 그 정보로하는 일이 다를 것이라고 생각하지만 항상 일관 적입니다.
이것은 오래된 질문이며 경로 변경을 추진하기 위해 경로 변경을 경청해야하는 비즈니스 요구를 잘 이해하지 못합니다. 로터리처럼 보입니다.
그러나 원하는 것은 'page_path'
Google 분석 / 글로벌 사이트 태그 / 이와 유사한 것에 대한 반응 라우터 경로 변경 을 업데이트하는 것이기 때문에 여기에서 끝났다면 이제 사용할 수 있는 후크가 있습니다. 나는 받아 들인 대답을 기반으로 작성했습니다.
useTracking.js
import { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
export const useTracking = (trackingId) => {
const { listen } = useHistory()
useEffect(() => {
const unlisten = listen((location) => {
// if you pasted the google snippet on your index.html
// you've declared this function in the global
if (!window.gtag) return
window.gtag('config', trackingId, { page_path: location.pathname })
})
// remember, hooks that add listeners
// should have cleanup to remove them
return unlisten
}, [trackingId, listen])
}
이 후크 는 앱에서 한 번 , 상단 근처에 있지만 여전히 라우터 내부에 사용해야 합니다. 나는 App.js
다음과 같이 보입니다.
App.js
import * as React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './Home/Home'
import About from './About/About'
// this is the file above
import { useTracking } from './useTracking'
export const App = () => {
useTracking('UA-USE-YOURS-HERE')
return (
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
)
}
// I find it handy to have a named export of the App
// and then the default export which wraps it with
// all the providers I need.
// Mostly for testing purposes, but in this case,
// it allows us to use the hook above,
// since you may only use it when inside a Router
export default () => (
<BrowserRouter>
<App />
</BrowserRouter>
)
React 단일 페이지 앱에서 새 화면으로 이동 한 후 ChromeVox 스크린 리더를 "화면"상단에 집중하려고 할 때이 질문을 받았습니다. 기본적으로 새 서버 렌더링 웹 페이지에 대한 링크를 따라이 페이지가로드되면 어떤 일이 발생할지 모방하려고합니다.
이 솔루션은 리스너가 필요하지 않습니다, 그것은 사용 withRouter()
과 componentDidUpdate()
수명주기 방법은 새로운 URL 경로를 탐색 할 때 원하는 요소에 ChromeVox에 초점을 클릭을 트리거 할 수 있습니다.
모든 앱 화면을 포함하는 react-router 스위치 태그를 감싸는 "Screen"구성 요소를 만들었습니다.
<Screen>
<Switch>
... add <Route> for each screen here...
</Switch>
</Screen>
Screen.tsx
구성 요소참고 : 이 구성 요소는 React + TypeScript를 사용합니다.
import React from 'react'
import { RouteComponentProps, withRouter } from 'react-router'
class Screen extends React.Component<RouteComponentProps> {
public screen = React.createRef<HTMLDivElement>()
public componentDidUpdate = (prevProps: RouteComponentProps) => {
if (this.props.location.pathname !== prevProps.location.pathname) {
// Hack: setTimeout delays click until end of current
// event loop to ensure new screen has mounted.
window.setTimeout(() => {
this.screen.current!.click()
}, 0)
}
}
public render() {
return <div ref={this.screen}>{this.props.children}</div>
}
}
export default withRouter(Screen)
focus()
대신을 ( 를) 사용해 click()
보았지만 클릭하면 ChromeVox가 현재 읽고있는 내용을 읽지 않고 시작하도록 지시 한 위치에서 다시 시작합니다.
고급 참고 : 이 솔루션에서는 <nav>
Screen 구성 요소 내부에서 <main>
콘텐츠 이후에 렌더링되는 탐색 이 main
using css 위에 시각적으로 배치 order: -1;
됩니다. 따라서 의사 코드에서 :
<Screen style={{ display: 'flex' }}>
<main>
<nav style={{ order: -1 }}>
<Screen>
이 솔루션에 대한 생각, 의견 또는 팁이 있으면 의견을 추가하십시오.
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Sidebar from './Sidebar';
import Chat from './Chat';
<Router>
<Sidebar />
<Switch>
<Route path="/rooms/:roomId" component={Chat}>
</Route>
</Switch>
</Router>
import { useHistory } from 'react-router-dom';
function SidebarChat(props) {
**const history = useHistory();**
var openChat = function (id) {
**//To navigate**
history.push("/rooms/" + id);
}
}
**//To Detect the navigation change or param change**
import { useParams } from 'react-router-dom';
function Chat(props) {
var { roomId } = useParams();
var roomId = props.match.params.roomId;
useEffect(() => {
//Detect the paramter change
}, [roomId])
useEffect(() => {
//Detect the location/url change
}, [location])
}