Reputation: 3943
I've got an issue with React.js. I want to add another property (productGroups
) to an existing state (this.state.mainProductGroups
- type object array
). So I want to find out the corresponding entry in the array and add the new property to it.
This is my function:
getProductGroups(mainProductGroupId) {
$.ajax({
type: "POST",
context:this,
dataType: "json",
async: true,
url: "ajax.php",
data: ({
requestType: 'getProductGroups',
countryID: this.state.countryObject.countryNo,
languageID: Language[this.state.currentLanguage].languageNo,
mainProductGroupID: mainProductGroupId,
}),
success: function (data) {
let mainProductGroups = this.state.mainProductGroups;
let mainPGFound = false;
let mainPG = mainProductGroups.filter(mainProductGroup => mainProductGroup.id == mainProductGroupId);
mainPG.productGroups = data.productGroups;
this.setState({
mainProductGroups: mainProductGroups,
});
}
});
}
Here is an data example of the this.state.mainProductGroups
:
The issue is now, that the productsGroup
property is not being filled. The ajax request returns correct values (also type object array
). Why is it not being updated? Is there a problem, because the initial value of the property productGroups
is string
and now I want to overwrite this with a type of object array
?
Upvotes: 0
Views: 76
Reputation: 3943
My final solution is this one.
getProductGroups(mainProductGroupId) {
$.ajax({
type: "POST",
context:this,
dataType: "json",
async: true,
url: "ajax.php",
data: ({
requestType: 'getProductGroups',
countryID: this.state.countryObject.countryNo,
languageID: Language[this.state.currentLanguage].languageNo,
mainProductGroupID: mainProductGroupId,
}),
success: (data) => {
let mainProductGroups = this.state.mainProductGroups.map((mainProductGroup) => {
if(mainProductGroup.id === mainProductGroupId) {
mainProductGroup.productGroups = data.productGroups;
}
return mainProductGroup;
});
this.setState({
mainProductGroups: mainProductGroups,
});
}
});
}
I think, the reason was that I did not change the state property mainProductGroups
at all in my first solution. Now it is working fine. Thanks all for your help.
Upvotes: 1
Reputation: 81
Manoz is right about this
losing context in a regular function. I would just like to take it a little further and actually extract that function into its own component method, so you'd end up with something like this:
updateMainProductGroups = data => {
const { mainProductGroups } = this.state;
const mainPG = mainProductGroups.find(mainProductGroup =>
mainProductGroup.id === mainProductGroupId
);
mainPG.productGroups = data.productGroups;
this.setState({ mainProductGroups });
}
getProductGroups(mainProductGroupId) {
$.ajax({
type: "POST",
context: this,
dataType: "json",
async: true,
url: "ajax.php",
data: ({
requestType: 'getProductGroups',
countryID: this.state.countryObject.countryNo,
languageID: Language[this.state.currentLanguage].languageNo,
mainProductGroupID: mainProductGroupId,
}),
success: updateMainProductGroups
});
}
Note: I removed this line let mainPGFound = false;
which appears to not be used within this function, and I also changed filter
to find
, because you seem to be wanting to operate on a returned object, and filter
will actually give you back an array with that object inside.
Upvotes: 1
Reputation: 6587
Change your success handler to this
success: function (data) {}
from this
success: (data)=> {}
See when you set state while writing function
it is a new scope for this
context in your callback. So it won't find this
as this
from the context. What you need is a lexical scoping with arrow function. Which is something you need in this case.
The problem here is
Typically if we’re writing ES5, we’ll use something like Function.prototype.bind to grab the this value from another scope to change a function’s execution context. This will mainly be used in callbacks inside a different scope.
see more here
Upvotes: 1
Reputation: 741
Change
this.setState({
mainProductGroups: mainProductGroups,
});
to
this.setState({
mainProductGroups: mainPG.productGroups
});
Upvotes: 0