답변:
나는 소품 withRouter
을 얻기 위해 사용 합니다 location
. 새로운 경로로 인해 구성 요소가 업데이트되면 값이 변경되었는지 확인합니다.
@withRouter
class App extends React.Component {
static propTypes = {
location: React.PropTypes.object.isRequired
}
// ...
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
this.onRouteChanged();
}
}
onRouteChanged() {
console.log("ROUTE CHANGED");
}
// ...
render(){
return <Switch>
<Route path="/" exact component={HomePage} />
<Route path="/checkout" component={CheckoutPage} />
<Route path="/success" component={SuccessPage} />
// ...
<Route component={NotFound} />
</Switch>
}
}
그것이 도움이되기를 바랍니다.
withRouter
하고 있지만 오류가 발생 You should not use <Route> or withRouter() outside a <Router>
합니다. <Router/>
위 코드에 구성 요소 가 없습니다 . 어떻게 작동합니까?
<Switch>
구성 요소가 사실상의 라우터 역할을합니다. <Route>
일치하는 경로를 가진 첫 번째 항목 만 렌더링됩니다. <Router/>
이 시나리오에서는 구성 요소 가 필요 없습니다
위를 확장하려면 기록 개체를 가져와야합니다. 을 사용 하는 경우 히스토리 오브젝트의 특성 및 기능에 대한 소품을 통해 액세스 할 수 있도록 상위 컴포넌트 (HoC) 로 컴포넌트를 BrowserRouter
가져 withRouter
오고 랩핑 할 수 있습니다 .
import { withRouter } from 'react-router-dom';
const myComponent = ({ history }) => {
history.listen((location, action) => {
// location is an object like window.location
console.log(action, location.pathname, location.state)
});
return <div>...</div>;
};
export default withRouter(myComponent);
유일하게 알아 두어야 할 것은 라우터와 함께 접근 할 수있는 대부분의 다른 방법으로 history
소품을 구조화 할 때 소품을 오염시키는 것처럼 보입니다.
withRoutes
에 withRouter
.
히스토리 v4 lib 를 사용해야 합니다.
거기 에서 예
history.listen((location, action) => {
console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`)
console.log(`The last navigation action was ${action}`)
})
history.push
트리거 하는 것 같습니다 history.listen
. history v4 docs 에서 기본 URL 사용 예를 참조하십시오 . 실제로는 브라우저 의 기본 개체 래퍼 이기 때문에 기본 개체와 정확히 동일하게 동작하지 않습니다. history
history
const unlisten = history.listen(myListener); unlisten();
withRouter
, history.listen
및 useEffect
(React Hooks)는 매우 잘 작동합니다.
import React, { useEffect } from 'react'
import { withRouter } from 'react-router-dom'
const Component = ({ history }) => {
useEffect(() => history.listen(() => {
// do something on route change
// for my example, close a drawer
}), [])
//...
}
export default withRouter(Component)
리스너 콜백은 경로가 변경 될 때마다 발생하며에 대한 반환 값 history.listen
은으로 잘 작동하는 종료 처리기입니다 useEffect
.
v5.1은 유용한 후크를 소개합니다 useLocation
https://reacttraining.com/blog/react-router-v5-1/#uselocation
import { Switch, useLocation } from 'react-router-dom'
function usePageViews() {
let location = useLocation()
useEffect(
() => {
ga.send(['pageview', location.pathname])
},
[location]
)
}
function App() {
usePageViews()
return <Switch>{/* your routes here */}</Switch>
}
후크 포함 :
import { useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { history as historyShape } from 'react-router-prop-types'
const DebugHistory = ({ history }) => {
useEffect(() => {
console.log('> Router', history.action, history.location])
}, [history.location.key])
return null
}
DebugHistory.propTypes = { history: historyShape }
export default withRouter(DebugHistory)
<DebugHistory>
컴포넌트 로 가져 오기 및 렌더링
import React, { useEffect } from 'react';
import { useLocation } from 'react-router';
function MyApp() {
const location = useLocation();
useEffect(() => {
console.log('route has been changed');
...your code
},[location.pathname]);
}
후크
반응 후크를 사용하여 useEffect
const history = useHistory()
const queryString = require('query-string')
const parsed = queryString.parse(location.search)
const [search, setSearch] = useState(parsed.search ? parsed.search : '')
useEffect(() => {
const parsedSearch = parsed.search ? parsed.search : ''
if (parsedSearch !== search) {
// do some action! The route Changed!
}
}, [location.search])
어떤 경우에는 다음과 같이 render
속성 대신 속성을 사용할 수 있습니다 component
.
class App extends React.Component {
constructor (props) {
super(props);
}
onRouteChange (pageId) {
console.log(pageId);
}
render () {
return <Switch>
<Route path="/" exact render={(props) => {
this.onRouteChange('home');
return <HomePage {...props} />;
}} />
<Route path="/checkout" exact render={(props) => {
this.onRouteChange('checkout');
return <CheckoutPage {...props} />;
}} />
</Switch>
}
}
onRouteChange
방법에서 상태를 변경 하면 '최대 업데이트 깊이 초과'오류가 발생할 수 있습니다.
useEffect
후크를 사용하면 리스너를 추가하지 않고도 경로 변경을 감지 할 수 있습니다.
import React, { useEffect } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import Main from './Main';
import Blog from './Blog';
const App = ({history}) => {
useEffect( () => {
// When route changes, history.location.pathname changes as well
// And the code will execute after this line
}, [history.location.pathname]);
return (<Switch>
<Route exact path = '/' component = {Main}/>
<Route exact path = '/blog' component = {Blog}/>
</Switch>);
}
export default withRouter(App);
방금이 문제를 해결 했으므로 주어진 다른 답변에 대한 보충으로 솔루션을 추가 할 것입니다.
여기서 문제 useEffect
는 원할 때 실제로 작동하지 않는다는 것입니다. 첫 번째 렌더링 후에 만 호출이 트리거되므로 원하지 않는 지연이 있습니다.
redux와 같은 상태 관리자를 사용하는 경우 상점의 느린 상태로 인해 화면에서 깜박임이 발생할 가능성이 있습니다.
실제로 원하는 것은 useLayoutEffect
이것이 즉시 트리거되기 때문에 사용하는 것 입니다.
그래서 라우터와 같은 디렉토리에 작은 유틸리티 기능을 작성했습니다.
export const callApis = (fn, path) => {
useLayoutEffect(() => {
fn();
}, [path]);
};
구성 요소 HOC 내에서 다음과 같이 호출합니다.
callApis(() => getTopicById({topicId}), path);
path
를 match
사용할 때 객체에 전달되는 소품입니다 withRouter
.
나는 역사에서 수동으로 듣기 / 듣기를 좋아하지 않습니다. 그것은 단지 imo입니다.