react-router를 사용하여 반응 응용 프로그램을 작업 중입니다. 다음과 같은 URL이있는 프로젝트 페이지가 있습니다.
myapplication.com/project/unique-project-id
프로젝트 구성 요소가로드되면 componentDidMount 이벤트에서 해당 프로젝트에 대한 데이터 요청을 트리거합니다. 이제 두 프로젝트간에 직접 전환하면 ID 만 이와 같이 변경되는 문제가 발생합니다.
myapplication.com/project/982378632
myapplication.com/project/782387223
myapplication.com/project/198731289
componentDidMount가 다시 트리거되지 않으므로 데이터가 새로 고쳐지지 않습니다. 데이터 요청을 트리거하는 데 사용해야하는 다른 수명주기 이벤트 나이 문제를 해결하기위한 다른 전략이 있습니까?
답변
링크가 다른 매개 변수 만 사용하여 동일한 경로로 향하는 경우 다시 마운트되지 않고 대신 새 소품을받습니다. 따라서 componentWillReceiveProps(newProps)
함수를 사용하고 newProps.params.projectId
.
데이터를로드하려는 경우 라우터가 구성 요소의 정적 메서드를 사용하여 일치를 처리하기 전에 데이터를 가져 오는 것이 좋습니다. 이 예를 확인하십시오. React Router Mega Demo . 이렇게하면 구성 요소가 데이터를로드하고 경로 매개 변수가 변경 될 때 자동으로 업데이트됩니다 componentWillReceiveProps
.
답변
경로가 변경 될 때 구성 요소를 다시 마운트해야하는 경우 구성 요소의 키 속성에 고유 한 키를 전달할 수 있습니다 (키는 경로 / 경로와 연결됨). 따라서 경로가 변경 될 때마다 React 구성 요소가 마운트 해제 / 재 마운트하도록 트리거하는 키도 변경됩니다. 이 답변 에서 아이디어를 얻었습니다.
답변
위의 일부와 비슷하지만 코드가있는 내 대답은 다음과 같습니다.
<Route path="/page/:pageid" render={(props) => (
<Page key={props.match.params.pageid} {...props} />)
} />
답변
경로 변경으로 인해 페이지가 새로 고쳐지지는 않는다는 점을 분명히해야하며 직접 처리해야합니다.
import theThingsYouNeed from './whereYouFindThem'
export default class Project extends React.Component {
componentWillMount() {
this.state = {
id: this.props.router.params.id
}
// fire action to update redux project store
this.props.dispatch(fetchProject(this.props.router.params.id))
}
componentDidUpdate(prevProps, prevState) {
/**
* this is the initial render
* without a previous prop change
*/
if(prevProps == undefined) {
return false
}
/**
* new Project in town ?
*/
if (this.state.id != this.props.router.params.id) {
this.props.dispatch(fetchProject(this.props.router.params.id))
this.setState({id: this.props.router.params.id})
}
}
render() { <Project .../> }
}
답변
당신이 가지고 있다면:
<Route
render={(props) => <Component {...props} />}
path="/project/:projectId/"
/>
React 16.8 이상에서는 hooks를 사용하여 다음을 수행 할 수 있습니다.
import React, { useEffect } from "react";
const Component = (props) => {
useEffect(() => {
props.fetchResource();
}, [props.match.params.projectId]);
return (<div>Layout</div>);
}
export default Component;
거기에서는 변경 fetchResource
될 때마다 새 호출을 트리거합니다 props.match.params.id
.
답변
@wei, @ Breakpoint25 및 @PaulusLimma의 답변을 바탕으로 <Route>
. 이렇게하면 URL이 변경 될 때 페이지가 다시 마운트되어 페이지의 모든 구성 요소가 다시 렌더링되는 것이 아니라 생성되고 다시 마운트됩니다. 모든 componentDidMount()
다른 시작 후크는 URL 변경시에도 실행됩니다.
아이디어는 key
URL이 변경 될 때 컴포넌트 속성을 변경하는 것이며 이로 인해 React가 컴포넌트를 다시 마운트하게됩니다.
<Route>
예를 들어 다음과 같이에 대한 드롭 인 대체물로 사용할 수 있습니다 .
<Router>
<Switch>
<RemountingRoute path="/item/:id" exact={true} component={ItemPage} />
<RemountingRoute path="/stuff/:id" exact={true} component={StuffPage} />
</Switch>
</Router>
<RemountingRoute>
구성 요소는 다음과 같이 정의된다 :
export const RemountingRoute = (props) => {
const {component, ...other} = props
const Component = component
return (
<Route {...other} render={p => <Component key={p.location.pathname + p.location.search}
history={p.history}
location={p.location}
match={p.match} />}
/>)
}
RemountingRoute.propsType = {
component: PropTypes.object.isRequired
}
이것은 React-Router 4.3으로 테스트되었습니다.
답변
@wei의 대답 은 훌륭하게 작동하지만 어떤 상황에서는 내부 구성 요소의 키를 설정하지 않고 자체 경로를 지정하는 것이 더 낫습니다. 또한 구성 요소에 대한 경로가 정적이지만 사용자가 탐색 할 때마다 구성 요소를 다시 마운트하기를 원하면 (아마도 componentDidMount ()에서 API 호출을 수행하는 경우) location.pathname을 경로의 키로 설정하는 것이 편리합니다. 그것의 경로와 위치가 변경되면 모든 콘텐츠가 다시 마운트됩니다.
const MainContent = ({location}) => (
<Switch>
<Route exact path='/projects' component={Tasks} key={location.pathname}/>
<Route exact path='/tasks' component={Projects} key={location.pathname}/>
</Switch>
);
export default withRouter(MainContent)