[reactjs] 소품 변경시 React 컴포넌트 다시 렌더링
컨테이너 구성 요소에서 프레젠테이션 구성 요소를 분리하려고합니다. 나는 SitesTable
및 SitesTableContainer
. 컨테이너는 현재 사용자를 기반으로 적절한 사이트를 가져 오기 위해 redux 작업을 트리거하는 역할을합니다.
문제는 컨테이너 구성 요소가 처음에 렌더링 된 후 현재 사용자를 비동기 적으로 가져 오는 것입니다. 이 수단은 컨테이너 구성 요소는 자신의 코드를 다시 실행해야 함을 알고하지 않는 componentDidMount
받는 보낼 데이터를 업데이트 할 기능을 SitesTable
. props (user) 중 하나가 변경되면 컨테이너 구성 요소를 다시 렌더링해야한다고 생각합니다. 이 작업을 올바르게 수행하려면 어떻게합니까?
class SitesTableContainer extends React.Component {
static get propTypes() {
return {
sites: React.PropTypes.object,
user: React.PropTypes.object,
isManager: React.PropTypes.boolean
}
}
componentDidMount() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}
render() {
return <SitesTable sites={this.props.sites}/>
}
}
function mapStateToProps(state) {
const user = userUtils.getCurrentUser(state)
return {
sites: state.get('sites'),
user,
isManager: userUtils.isManager(user)
}
}
export default connect(mapStateToProps)(SitesTableContainer);
답변
componentDidUpdate
방법에 조건을 추가해야 합니다.
예제는 fast-deep-equal
객체를 비교하는 데 사용됩니다.
import equal from 'fast-deep-equal'
...
constructor(){
this.updateUser = this.updateUser.bind(this);
}
componentDidMount() {
this.updateUser();
}
componentDidUpdate(prevProps) {
if(!equal(this.props.user, prevProps.user)) // Check if it's a new user, you can also use some unique property, like the ID (this.props.user.id !== prevProps.user.id)
{
this.updateUser();
}
}
updateUser() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}
후크 사용 (React 16.8.0+)
import React, { useEffect } from 'react';
const SitesTableContainer = ({
user,
isManager,
dispatch,
sites,
}) => {
useEffect(() => {
if(isManager) {
dispatch(actions.fetchAllSites())
} else {
const currentUserId = user.get('id')
dispatch(actions.fetchUsersSites(currentUserId))
}
}, [user]);
return (
return <SitesTable sites={sites}/>
)
}
비교하려는 소품이 객체 또는 배열 인 경우 useDeepCompareEffect
대신을 사용해야 합니다 useEffect
.
답변
ComponentWillReceiveProps()
버그와 불일치로 인해 향후 지원이 중단 될 예정입니다. 소품 변화 요소를 재 렌더링을위한 대안 용액을 사용하는 것 ComponentDidUpdate()
및 ShouldComponentUpdate()
.
ComponentDidUpdate()
구성 요소가 업데이트 될 때마다 호출되고 ShouldComponentUpdate()
true를 반환하면 ( ShouldComponentUpdate()
정의되지 않은 경우 true
기본적으로 반환 됨)
shouldComponentUpdate(nextProps){
return nextProps.changedProp !== this.state.changedProp;
}
componentDidUpdate(props){
// Desired operations: ex setting state
}
이 동일한 동작은 ComponentDidUpdate()
내부에 조건문을 포함하여 메서드 만 사용하여 수행 할 수 있습니다 .
componentDidUpdate(prevProps){
if(prevProps.changedProp !== this.props.changedProp){
this.setState({
changedProp: this.props.changedProp
});
}
}
조건부없이 또는 ShouldComponentUpdate()
구성 요소 를 정의하지 않고 상태를 설정하려고 하면 무한히 다시 렌더링됩니다.
답변
KEY
소품으로 변경되는 고유 키 (데이터 조합)를 사용할 수 있으며 해당 구성 요소는 업데이트 된 소품으로 다시 렌더링됩니다.
답변
componentWillReceiveProps(nextProps) { // your code here}
나는 그것이 당신이 필요한 이벤트라고 생각합니다. componentWillReceiveProps
컴포넌트가 소품을 통해 무언가를받을 때마다 트리거됩니다. 거기에서 당신은 당신이 원하는 것을 할 수 있습니다.
답변
이 답변을 보는 것이 좋습니다. 을 그것이 당신이하는 일과 관련이 있는지 확인하는 것이 좋습니다. 실제 문제를 이해한다면 비동기 작업을 올바르게 사용하지 않고 redux “store”를 업데이트하면 자동으로 구성 요소가 새로운 소품으로 업데이트됩니다.
이 코드 섹션 :
componentDidMount() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}
구성 요소에서 트리거하지 않아야하며 첫 번째 요청을 실행 한 후에 처리해야합니다.
redux-thunk 에서이 예제를 살펴보십시오 .
function makeASandwichWithSecretSauce(forPerson) {
// Invert control!
// Return a function that accepts `dispatch` so we can dispatch later.
// Thunk middleware knows how to turn thunk async actions into actions.
return function (dispatch) {
return fetchSecretSauce().then(
sauce => dispatch(makeASandwich(forPerson, sauce)),
error => dispatch(apologize('The Sandwich Shop', forPerson, error))
);
};
}
반드시 redux-thunk를 사용할 필요는 없지만 이와 같은 시나리오를 추론하고 일치하는 코드를 작성하는 데 도움이됩니다.
답변
사용하기 쉬운 방법은 다음과 같습니다. prop이 업데이트되면 자동으로 컴포넌트를 다시 렌더링합니다.
render {
let textWhenComponentUpdate = this.props.text
return (
<View>
<Text>{textWhenComponentUpdate}</Text>
</View>
)
}