I have an array of objects addon_categories
containing a property id
and another array: addons
. As the user toggles checkboxes, the state should update accordingly: which includes adding to or removing from 'addons' array under the selected category.
this.state = { addon_categories: [] };
// example of filled state
this.state = { addon_categories: [
{ id: 3, addons: [ 1 ] },
{ id: 2, addons: [ 1, 4, 11 ] },
{ id: 4, addons: [ 3, 4] }
] };
This is more of a problem of JavaScript
more than React
except that the data has to be finally updated as a component state. As a beginner of JavaScript, I'm unable to update the state object with arrays of objects containing some properties and arrays. In the code below, what is the correct logic to update the addons
array (for both delete from and push to) just for the particular category?
Here's the logic:
If category ID doesn't exist, simply add a new object with the category id and addons array with single addon id. [✓]
If the category ID exists,
-> check if the addon_id exists in this category.
-> If addon_id exists in this category, remove the addon id from this addons array in this object [?]
-> If addon_id doesn't exist, push this addon id to this addons array in this object [?]
Here is my code.
import React from 'react';
import { connect } from 'react-redux';
import store from '../../../../reducers/store';
import fetchFood from '../../../../actions/restaurant/food_get';
class AddonsModal extends React.Component
{
constructor(props)
{
super(props);
this.state = { addon_categories: [] };
this.onAddonChange = this.onAddonChange.bind(this);
}
/*
* Handle click, toggle addon change
*/
onAddonChange(e)
{
const c = +e.target.name; // category_id from input
const a = +e.target.id; // addon_id from input
// create new instance of this.state.addon_categories
let addon_categories = this.state.addon_categories.slice();
if (!this.addonCategoryExists(c))
{
// CATEGORY DOESNT EXIST, SO NEW CATEGORY AND ADDON ADDED!
addon_categories.push({ id: c, addons: [a] });
this.setState({ addon_categories }, () => console.log('NEW STATE', this.state.addon_categories));
}
else
{
// CATEGORY EXISTS
if (this.addonExistsInCategory(c, a))
{
// ?? ADDON EXISTS IN THIS CATEGORY, SO NEED TO REMOVE IT
}
else
{
// ?? ADDON DOESNT EXIST IN CATEGORY SO NEED TO ADD IT TO JUST THIS CATEGORY
}
}
}
addonCategoryExists(c)
{
return !! this.state.addon_categories.filter(category => category.id === c).length;
}
addonExistsInCategory(c, a)
{
let verified = false;
let categories = this.state.addon_categories.filter(category => category.id === c);
categories.forEach(category =>
{
if (category.addons.includes(a)) { verified = true; }
});
return verified;
}
componentDidMount()
{
store.dispatch(fetchFood(this.props.Restaurant.id, this.props.food.id));
}
render()
{
let food = this.props.food;
let foodData = this.props.foodDetails.food.data;
let addon_categories = foodData ? foodData.data.addon_category : null;
return (
<div className="row">
{addon_categories && addon_categories.map(category => { return (
<div className="col-xs-12" key={category.id}>
<div className="pop-up-dish-specials">
<h2>{category.name}</h2>
{category.addons && category.addons.map(addon => { return (
<div key={addon.id}>
{/* for simplicity, i've sent the category_id in name and addon_id in id property */}
<input type="checkbox" name={category.id} id={addon.id} onChange={this.onAddonChange}/>
<label htmlFor={addon.id}>{addon.name}</label>
</div>
)})}
</div>
</div>
)})}
</div>
)
}
}
function mapStateToProps(state)
{
return { foodDetails: state.foodDetails }
}
export default connect(mapStateToProps)(AddonsModal);
if (this.addonExistsInCategory(c, a)) {
// ADDON EXISTS IN THIS CATEGORY, SO NEED TO REMOVE IT
addon_categories.find(function(obj) {
if (obj.id == c) {
obj.addons.splice(obj.addons.indexOf(a), 1);
}
});
} else {
// ADDON DOESNT EXIST IN CATEGORY SO NEED TO ADD IT TO JUST THIS CATEGORY
addon_categories.find(function(obj) {
if (obj.id == c) {
obj.addons.push(a);
}
});
}
this.setState({ addon_categories }, () => console.log('NEW STATE', this.state.addon_categories));
I would just use simple .map and .filter if addon exists, therefore for removal:
const newCategories = this.state.addon_categories.map(category => {
if (category.id === c) {
const newAddons = category.addons.filter(addon => addon !== a);
return { id: category.id, addons: newAddons };
} else {
return category;
}
});
this.setState({ addon_categories: newCategories });
for adding it would be like this:
const newCategories = this.state.addon_categories.map(category => {
if (category.id === c) {
const newAddons = category.addons.concat([a])
return { id: category.id, addons: newAddons };
} else {
return category;
}
});
this.setState({ addon_categories: newCategories });
There is probably better solution to this problem though.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.