경로 매개 변수가 변경 될 때 구성 요소가 다시 마운트되지 않음
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 .../> }
}
@wei, @ Breakpoint25 및 @PaulusLimma의 답변을 바탕으로 <Route>. 이렇게하면 URL이 변경 될 때 페이지가 다시 마운트되어 페이지의 모든 구성 요소가 다시 렌더링되는 것이 아니라 생성되고 다시 마운트됩니다. 모든 componentDidMount()다른 시작 후크는 URL 변경시에도 실행됩니다.
아이디어는 keyURL이 변경 될 때 컴포넌트 속성을 변경하는 것이며 이로 인해 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's answer works great, but in some situations I find it better to not set a key of inner component, but route itself. Also, if path to component is static, but you just want component to remount each time user navigates to it (perhaps to make an api-call at componentDidMount()), it is handy to set location.pathname to key of route. With it route and all it's content gets remounted when location changes.
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)
This is how I solved the problem:
This method gets the individual item from the API:
loadConstruction( id ) {
axios.get('/construction/' + id)
.then( construction => {
this.setState({ construction: construction.data })
})
.catch( error => {
console.log('error: ', error);
})
}
I call this method from componentDidMount, this method will be called just once, when I load this route for the first time:
componentDidMount() {
const id = this.props.match.params.id;
this.loadConstruction( id )
}
And from componentWillReceiveProps which will be called since the second time we load same route but different ID, and I call the first method to reload the state and then component will load the new item.
componentWillReceiveProps(nextProps) {
if (nextProps.match.params.id !== this.props.match.params.id) {
const id = nextProps.match.params.id
this.loadConstruction( id );
}
}
If you have:
<Route
render={(props) => <Component {...props} />}
path="/project/:projectId/"
/>
In React 16.8 and above, using hooks, you can do:
import React, { useEffect } from "react";
const Component = (props) => {
useEffect(() => {
props.fetchResource();
}, [props.match.params.projectId]);
return (<div>Layout</div>);
}
export default Component;
In there, you are only triggering a new fetchResource call whenever props.match.params.id changes.
react-router is broken because it must remount components on any location change.
I managed to find a fix for this bug though:
https://github.com/ReactTraining/react-router/issues/1982#issuecomment-275346314
In short (see the link above for full info)
<Router createElement={ (component, props) =>
{
const { location } = props
const key = `${location.pathname}${location.search}`
props = { ...props, key }
return React.createElement(component, props)
} }/>
This will make it remount on any URL change
참고URL : https://stackoverflow.com/questions/32261441/component-does-not-remount-when-route-parameters-change
'Program Club' 카테고리의 다른 글
| View.GONE이있는 Android View는 여전히 onTouch 및 onClick을 수신합니다. (0) | 2020.10.22 |
|---|---|
| Django는 쿼리에 대해 존재하는지 확인합니다. (0) | 2020.10.22 |
| ClipData.Item.getUri를 통해 앱 외부에 노출 (0) | 2020.10.22 |
| Android 레이아웃 내부에서 뷰를 중앙에 배치하는 방법은 무엇입니까? (0) | 2020.10.22 |
| UITextField 자리 표시 자 색상 변경 (0) | 2020.10.22 |