2017-07-26 96 views
1

我有一個對象數組addon_categories包含一個屬性id和另一個數組:addons。當用戶切換複選框時,狀態應該相應更新:其中包括添加或刪除所選類別下的「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數組中刪除addon 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); 

回答

1

我只想用簡單的.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 }); 

儘管這個問題可能有更好的解決方案。

+0

這是很好的解決方案,非常感謝。 – anonym

+0

我想進一步分解兩個刪除條件。 '[#1]'刪除整個'addon_category對象',如果它是其中唯一的插件,'[#2。]'如果有多個(完成✓),就從陣列中刪除插件。我無法使用'if(category.id === c && category.addons.length === 1){return addon_categories.splice(index,1); }' – anonym

+0

您的解決方案將無法正常工作,因爲拼接會返回已刪除的項目,因此它不會對您有所幫助。你可以做2件事 - 或者只是修改我的代碼返回到這樣的'newAddons.length? {id:category.id,addons:newAddons}:undefined',然後在設置狀態時,您將執行addon_categories:newCategories.filter(category => category)'(這樣您可以從數組中過濾一個未定義的值。這樣做是爲了保存類別索引值,然後在設置狀態之前使用splice從newCategories中刪除它。 –

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

@Oliver如果這樣可以解決您的查詢問題,那麼您可以將其標記爲答案 –

+0

這樣可以解決您的問題,而非您的問題。 – anonym