상태 변경 시 반응 구성 요소가 다시 렌더링되지 않음
콘텐츠를 얻기 위해 API로 이동하는 리액트 클래스가 있습니다.데이터가 반환되는 것을 확인했지만 다시 렌더링되지 않습니다.
var DealsList = React.createClass({
getInitialState: function() {
return { deals: [] };
},
componentDidMount: function() {
this.loadDealsFromServer();
},
loadDealsFromServer: function() {
var newDeals = [];
chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
newDeals = deals;
});
this.setState({ deals: newDeals });
},
render: function() {
var dealNodes = this.state.deals.map(function(deal, index) {
return (
<Deal deal={deal} key={index} />
);
});
return (
<div className="deals">
<table>
<thead>
<tr>
<td>Name</td>
<td>Amount</td>
<td>Stage</td>
<td>Probability</td>
<td>Status</td>
<td>Exp. Close</td>
</tr>
</thead>
<tbody>
{dealNodes}
</tbody>
</table>
</div>
);
}
});
단, 다음 명령어를 추가할 경우debugger
아래와 같이newDeals
이 입력되어 있고, 계속 진행하면 데이터가 표시됩니다.
loadDealsFromServer: function() {
var newDeals = [];
chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
newDeals = deals;
});
debugger
this.setState({ deals: newDeals });
},
콜링 딜 리스트는 다음과 같습니다.
var Gmail = React.createClass({
render: function() {
return (
<div className="main">
<div className="panel">
<DealsList person={this.props.person} />
</div>
</div>
);
}
});
여기에 엄청나게 간단한 것을 덧붙이고 싶지만, 오, 너무 쉽게 글을 쓰는 실수를 했어요.
this.state.something = 'changed';
...그리고 왜 렌더링과 구글 검색 및 이 페이지가 뜨지 않는지 이해하지 못했는데, 다음과 같이 썼어야 했다는 것을 깨달았습니다.
this.setState({something: 'changed'});
React는 다음을 사용하는 경우에만 재렌더를 트리거합니다.setState
상태를 갱신합니다.
제 시나리오는 조금 달랐어요.그리고 나는 나 같은 많은 신입생들이 당황할 것이라고 생각한다 - 그래서 여기서 공유한다.
my state 변수는 다음과 같이 useState를 사용하여 관리되는 JSON 개체의 배열입니다.
const [toCompare, setToCompare] = useState([]);
단, 아래 함수와 같이 toCompare를 setToCompare로 업데이트하면 re-render가 실행되지 않습니다.그리고 다른 부품으로 옮기는 것도 효과가 없었습니다.다른 이벤트가 재발송되는 경우에만 갱신된 리스트가 표시되었습니다.
const addUniversityToCompare = async(chiptoadd) =>
{
var currentToCompare = toCompare;
currentToCompare.push(chiptoadd);
setToCompare(currentToCompare);
}
이게 제 해결책이었어요.기본적으로 어레이를 할당하는 것은 참조를 복사하는 것이며, 어레이에 대한 참조는 변경되지 않기 때문에 어레이 내의 콘텐츠만 변경으로 간주되지 않습니다.다음 코드에서는 슬라이스를 사용하여 어레이를 복사하고 변경 없이 변경 후 다시 할당했습니다.완벽하게 잘 작동합니다.
const addUniversityToCompare = async (chiptoadd) => {
var currentToCompare = toCompare.slice();
currentToCompare.push(chiptoadd);
setToCompare(currentToCompare);
}
그게 나 같은 사람에게 도움이 됐으면 좋겠어.제가 틀렸다고 느끼거나 다른 방법이 있다면 알려주세요.
잘 부탁드립니다.
그 이유는 그 응답은chrome.runtime.sendMessage
는 비동기적입니다.조작 순서는 다음과 같습니다.
var newDeals = [];
// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
// (3) sometime in the future, this function runs,
// but it's too late
newDeals = deals;
});
// (2) this is called immediately, `newDeals` is an empty array
this.setState({ deals: newDeals });
디버거를 사용하여 스크립트를 일시 정지하면 콜백을 호출할 수 있는 내선 시간이 주어집니다.계속 진행하면 데이터가 도착하여 정상적으로 동작하는 것처럼 보입니다.
수정하려면 , 다음의 작업을 실시합니다.setState
데이터가 Chrome 내선번호에서 돌아온 후 호출:
var newDeals = [];
// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
// (2) sometime in the future, this function runs
newDeals = deals;
// (3) now you can call `setState` with the data
this.setState({ deals: newDeals });
}.bind(this)); // Don't forget to bind(this) (or use an arrow function)
[편집]
이 방법으로 문제가 해결되지 않으면 이 질문에 대한 다른 답변을 확인하십시오. 이 답변은 구성 요소가 업데이트되지 않을 수 있는 다른 이유를 설명합니다.
또 하나의 아주 쉬운 실수가 문제의 근원이었습니다.내가 직접 썼어shouldComponentUpdate
방법.
상태를 올바르게 업데이트하려면 어레이를 변환하지 마십시오.배열 복사본을 생성한 다음 복사된 배열의 상태를 설정해야 합니다.
const [deals, setDeals] = useState([]);
function updateDeals(deal) {
const newDeals = [...deals]; // spreading operator which doesn't mutate the array and returns new array
newDeals.push(deal);
// const newDeals = deals.concat(deal); // concat merges the passed value to the array and return a new array
// const newDeals = [...deals, deal] // directly passing the new value and we don't need to use push
setDeals(newDeals);
}
경우에는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.this.setState({})
맞긴 맞는데 제 기능이 여기에 얽매이지 않아서 안 되더라고요." " " .bind(this)
콜 콜의 실행this.foo = this.foo.bind(this)
정했습습니니다
나의 문제는 'React'를 사용한다는 것이었다.'React'를 사용해야 할 때 PureComponent'를 선택합니다.컴포넌트'입니다.
업데이트 중이고, 리듀서에 전달된 동일한 오브젝트를 반품하고 있습니다.이렇게 상태 객체를 반환하기 직전에 요소를 복사하여 수정했습니다.
Object.assign({}, state)
React-Native에서도 API 응답과 거부 상태가 갱신되지 않는 문제를 겪고 있었습니다.
apiCall().then(function(resp) { this.setState({data: resp}) // wasn't updating }
는 문제를 했다.function
apiCall().then((resp) => {
this.setState({data: resp}) // rendering the view as expected
}
을 사용법하면 화살표 되었습니다.this
은 항상
많은 답변(대부분의 답변은 시나리오에 맞는 답변)을 검토했지만, 어느 답변도 문제를 해결하지 못한 후, 저는 제 사례가 조금 다르다는 것을 깨달았습니다.
이상한 시나리오에서는 컴포넌트가 주(州) 내에서 렌더링되고 있었기 때문에 업데이트할 수 없었습니다.다음은 간단한 예입니다.
constructor() {
this.myMethod = this.myMethod.bind(this);
this.changeTitle = this.changeTitle.bind(this);
this.myMethod();
}
changeTitle() {
this.setState({title: 'I will never get updated!!'});
}
myMethod() {
this.setState({body: <div>{this.state.title}</div>});
}
render() {
return <>
{this.state.body}
<Button onclick={() => this.changeTitle()}>Change Title!</Button>
</>
}
바디를 상태로부터 렌더링하지 않도록 코드를 리팩터링한 후 정상적으로 동작:)
비슷한 문제를 안고 있지만 컴포넌트를 클래스화하고 리액트 리덕터를 사용하는 경우 --> api 콜을 리덕터 외부로 이동합니다.리듀서는 api 호출을 실행해서는 안 됩니다.자세한 대응은 https://stackoverflow.com/a/39516485/12121297 를 참조해 주세요.
언급URL : https://stackoverflow.com/questions/25937369/react-component-not-re-rendering-on-state-change
'sourcetip' 카테고리의 다른 글
wordpress 플러그인의 다른 페이지로 양식을 제출하는 방법 (0) | 2023.04.03 |
---|---|
반응 헬메트의 목적은 무엇입니까? (0) | 2023.04.03 |
커스텀 속성별로 WooCommerce 제품을 필터링하는 방법 (0) | 2023.04.03 |
django-rest-display 3.0은 네스트된 시리얼라이저로 작성 또는 갱신합니다. (0) | 2023.04.03 |
Oracle에서 활성/열린 연결을 나열하는 방법 (0) | 2023.04.03 |