如何通过从对象数组更新特定对象中的数组来更新状态?

时间:2017-07-26 11:25:49

标签: javascript reactjs

我有一个包含属性addon_categories的对象数组id和另一个数组addons。当用户切换复选框时,状态应相应更新:包括在所选类别下添加或删除“插件”数组。

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] }
 ] };

除了必须最终将数据更新为组件状态之外,这更多是JavaScript超过React的问题。作为JavaScript的初学者,我无法使用包含某些属性和数组的对象数组更新状态对象。在下面的代码中,为特定类别更新addons数组(对于删除和推送)的正确逻辑是什么?

这是逻辑:

  1. 如果类别ID不存在,只需添加一个类别为id的新对象和一个带有单个插件ID的插件数组。 [✓]

  2. 如果存在类别ID,则 - >检查此类别中是否存在addon_id。
    - >如果此类别中存在addon_id,请从此对象[?]中删除此addons数组中的插件ID - >如果addon_id不存在,请将此插件ID添加到此对象中的此插件数组中[?]

  3. 这是我的代码。

    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);
    

2 个答案:

答案 0 :(得分:1)

    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));

答案 1 :(得分:1)

如果存在addon,我会使用简单的.map和.filter,因此要删除:

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 });

添加它将是这样的:

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 });

但这个问题可能有更好的解决办法。