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

标签 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 不存在,则将此addon_id 推送到此对象中的此addons 数组[?]

这是我的代码。

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

最佳答案

如果插件存在,我将只使用简单的 .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 });

虽然这个问题可能有更好的解决方案。

关于javascript - 如何通过从对象数组更新特定对象中的数组来更新状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45325576/

相关文章:

javascript - jQuery "after-click"事件

javascript - div 在用户操作时更改其内容后的 Click 和 If 函数

javascript - Electron ,contextIsolation和contextBridge

html - 为什么 React 没有 "class"属性?

javascript - 输入数字输入后 Angular ng-model 不更新

javascript - 从数据列表中添加/删除元素两次或更多次时出现问题

javascript - 将基于类的组件重构为功能组件

reactjs - 如何在 React Native 中重置 Animated.Value?

javascript - 格式化从 JSON 文件接收数据的 React 表

javascript - 带有 ReactJS 的工具提示 div