私は私の心を失っています。多分あなたは私を助けることができます。マウントされたコンポーネントのcomponentDidUpdate
内でプロップが変更されたことを検出しようとしています。過去には問題なく動作しました。私はうまく機能しているテスト(以下のコードではrefreshData
)さえ持っています。 SOMEHOWがcomponentDidUpdate(prevProps)
で検出されない方法で小道具を渡すことは可能ですか?
component.js:
componentDidUpdate(prevProps){
//works fine
if ( this.props.refreshData !== prevProps.refreshData ) {
if ( this.props.refreshData )
this.refreshData();
}
//these two arent calling
if ( this.props.selectedCountries !== prevProps.selectedCountries ) {
if ( this.props.selectedCountries )
console.log('updated selected countries');
}
if ( this.props.selectedLocations !== prevProps.selectedLocations ) {
console.log('updated selected locations');
}
}
app.jsで次のような小道具を渡します:
selectLocation = (id, type, lng, lat, polydata, name, clear = false) => {
//console.log(type);
//console.log(lng);
//console.log(lat);
//console.log(polydata);
let selectedType = 'selected' + type;
let previousState = [];
if (clear) {
this.setState({
selectedCountries: [],
selectedLocations: [],
selectedServices: [],
selectedPoints: [],
mapCenter: [lng, lat],
locationGeoCoords: [polydata]
})
previousState.Push(id);
} else {
previousState = this.state[selectedType];
if (previousState.indexOf(id) === -1) {
//Push id
previousState.Push(id);
} else {
//remove id
var index = previousState.indexOf(id)
previousState.splice(index, 1);
}
}
if (type === "Countries") {
this.setState({
selectedCountries: previousState,
refreshData: true,
})
} else if (type === "Locations") {
this.setState({
selectedLocations: previousState,
refreshData: true
})
} else if (type === "Points") {
this.setState({
selectedPoints: previousState,
refreshData: true
})
}
}
render() {
return (
<component
selectedCountries={this.state.selectedCountries}
selectedLocations={this.state.selectedLocations}
refreshData={this.state.refreshData} />
}
}
こんにちは:)私のコメントで述べたように、問題はApp.jsファイルにあります-配列を変更しています。つまり、受け継ぐために選択した国の新しい配列を作成していると考えている場合、実際には元の配列を更新しているので、比較を行うときは常に2つのまったく同じ配列を比較しています。
App.jsを次のように更新してみてください-
_selectLocation = (id, type, lng, lat, polydata, name, clear = false) => {
//console.log(type);
//console.log(lng);
//console.log(lat);
//console.log(polydata);
let selectedType = 'selected' + type;
let previousState = [];
if (clear) {
this.setState({
selectedCountries: [],
selectedLocations: [],
selectedServices: [],
selectedPoints: [],
mapCenter: [lng, lat],
locationGeoCoords: [polydata]
})
previousState.Push(id);
} else {
previousState = [].concat(this.state[selectedType]);
if (previousState.indexOf(id) === -1) {
//Push id
previousState.Push(id);
} else {
//remove id
var index = previousState.indexOf(id)
previousState.splice(index, 1);
}
}
if (type === "Countries") {
this.setState({
selectedCountries: previousState,
refreshData: true,
})
} else if (type === "Locations") {
this.setState({
selectedLocations: previousState,
refreshData: true
})
} else if (type === "Points") {
this.setState({
selectedPoints: previousState,
refreshData: true
})
}
}
render() {
return (
<component
selectedCountries={this.state.selectedCountries}
selectedLocations={this.state.selectedLocations}
refreshData={this.state.refreshData} />
}
}
_
唯一の違いは、あなたがpreviousState
を設定した行です-私はそれを次のように更新しました
previousState = [].concat(this.state[selectedType]);
_[].concat
_を追加することにより、毎回新しい配列を効率的に作成しているので、Push
/splice
を介して配列に変更を適用すると、新しい配列のみが変更されます。 。その後、小道具としてそれを渡すと、比較は正しく機能します:)
あなたの読書の興味のために、これについて少し話す記事を見つけました: https://medium.com/pro-react/a-brief-talk-about-immutability-and-react-s-helpers- 70919ab8ae7c
selectedCountries
とselectedLocations
は配列オブジェクトです。それの参照は決して変更されません。代わりに、長さを確認してください。
componentDidUpdate(prevProps){
if ( this.props.refreshData !== prevProps.refreshData ) {
if ( this.props.refreshData )
this.refreshData();
}
if ( this.props.selectedCountries.length > prevProps.selectedCountries.length ) {
if ( this.props.selectedCountries )
console.log('updated selected countries');
}
if ( this.props.selectedLocations.length > prevProps.selectedLocations.length ) {
console.log('updated selected locations');
}
}
上記のコードスニペットでは、this.state
を直接変更しているようです。状態は不変である必要があります。状態を元の配列に変更するのではなく、新しい配列を作成するときに、要素を追加する場合はconcat
を、削除する場合はfilter
を必ず確認してください。私はこれらの行で何かをします。
また、コンポーネント名を大文字にすることもお勧めします。
selectLocation = (id, type, lng, lat, polydata, name, clear = false) => {
//console.log(type);
//console.log(lng);
//console.log(lat);
//console.log(polydata);
let selectedType = "selected" + type;
let previousState = [];
let updatedData = [];
if (clear) {
this.setState({
selectedCountries: [],
selectedLocations: [],
selectedServices: [],
selectedPoints: [],
mapCenter: [lng, lat],
locationGeoCoords: [polydata]
});
} else {
const data = this.state[selectedType];
if (data.indexOf(id) === -1) {
//Push id
updatedData = [...data, id];
} else {
updatedData = data.filter((value) => value !== id);
}
}
if(type) {
this.setState({
[selectedType]: updatedData,
refreshData: true
});
}
};
render() {
return (
<component
selectedCountries={this.state.selectedCountries}
selectedLocations={this.state.selectedLocations}
refreshData={this.state.refreshData}
/>
);
}
}
場所と国の小道具が実際に変化していることを確認しましたか?はいの場合、次のコードが機能するはずです。
componentDidUpdate(prevProps) {
if (this.props.selectedCountries.length !== prevProps.selectedCountries.length) {
console.log("updated selected countries");
}
if (this.props.selectedLocations.length !== prevProps.selectedLocations.length) {
console.log("updated selected locations");
}
}
ここに効果を紹介するためのフィドルを作成しました: https://codesandbox.io/s/o580n8lnv5