घटक राज्य में सरणी से तत्व निकालना


131

मैं एक घटक की स्थिति में एक सरणी से एक तत्व को निकालने का सबसे अच्छा तरीका खोजने की कोशिश कर रहा हूं। चूँकि मुझे this.stateचर को सीधे संशोधित नहीं करना चाहिए , क्या किसी तत्व को किसी सरणी से एक तत्व को हटाने का बेहतर तरीका (अधिक संक्षिप्त) है जो मैं यहाँ हूँ ?:

  onRemovePerson: function(index) {
    this.setState(prevState => { // pass callback in setState to avoid race condition
      let newData = prevState.data.slice() //copy array from prevState
      newData.splice(index, 1) // remove element
      return {data: newData} // update state
    })
  },

धन्यवाद।

अद्यतन

इसे सेटस्टेट में कॉलबैक का उपयोग करने के लिए अद्यतन किया गया है। इसे अद्यतन करते समय वर्तमान स्थिति का संदर्भ देते समय किया जाना चाहिए।


फेसबुक से ImmutableJS पर एक नज़र डालें जो रिएक्ट के साथ अच्छा काम करता है। लिंक
जोनाटन लुंडकविस्ट मेडन

6
मुझे आपके कोड में कुछ भी गलत नहीं दिख रहा है। वास्तव में यह बहुत ही मुहावरेदार तरीका है।
दिमित्र दिमित्रोव

जवाबों:


138

ऐसा करने का सबसे साफ तरीका जो मैंने देखा है वह है filter:

removeItem(index) {
  this.setState({
    data: this.state.data.filter((_, i) => i !== index)
  });
}

18
@HussienK का _उपयोग कभी-कभी एक अप्रयुक्त तर्क का प्रतिनिधित्व करने के लिए किया जाता है। यहां, यह सरणी में वर्तमान आइटम है।
क्रिसम

1
गजब का। मैं हर समय .filter का उपयोग कर रहा हूं, लेकिन इस स्थिति में इसका उपयोग करने के लिए कभी नहीं सोचा गया। : D
dakt

4
यह स्वच्छ कोड है, हालांकि, बड़े सरणियों के लिए, यह विधि धीमी है। कारण यह है कि, यह एक सूचकांक को खोजने के लिए पूरे सरणी से गुजरता है जो पहले से निर्धारित होता है।
मैट एलिस

1
@MattEllis चूंकि रिएक्ट के राज्य अपडेट वैसे भी अपरिवर्तनीय हैं, इसलिए आप किसी भी मामले में इसे कॉपी करने के लिए सूची के आकार में O (n) का उपयोग करने जा रहे हैं। मुझे आश्चर्य होगा अगर यह एक महत्वपूर्ण प्रदर्शन हिट था।
एफ्रियन

4
this.stateइनपुट के रूप में मूल्यांकन this.setState(), यहां तक ​​कि अपरिवर्तनीय रूप से , अनुशंसित नहीं है। कृपया इस विषय पर आधिकारिक प्रतिक्रिया डॉक्स के संदर्भ के लिए मेरा उत्तर देखें।
pscl

87

आप से update()अपरिवर्तनीय सहायक काreact-addons-update उपयोग कर सकते हैं , जो प्रभावी रूप से हुड के नीचे एक ही काम करता है, लेकिन आप जो कर रहे हैं वह ठीक है।

this.setState(prevState => ({
  data: update(prevState.data, {$splice: [[index, 1]]})
}))

:)
Koen

7
react-addons-updateअब पदावनत (2016) है। immutability-helperएक प्रतिस्थापन के रूप में उपलब्ध है। github.com/kolodny/immutability-helper इसके अलावा कृपया मेरे उत्तर नीचे देखें।
pscl

62

मेरा मानना ​​है कि this.stateअंदर संदर्भित setState()को हतोत्साहित किया जाता है ( राज्य अपडेट्स असिंक्रोनस हो सकते हैं )।

डॉक्स setState()एक कॉलबैक फ़ंक्शन के साथ उपयोग करने की सलाह देते हैं ताकि अपडेट होने पर प्रबलिंग को रनटाइम में पारित किया जाए। तो यह है कि यह कैसा दिखेगा:

ES6 के बिना Array.prototype.filter का उपयोग करना

removeItem : function(index) {
  this.setState(function(prevState){
    return { data : prevState.data.filter(function(val, i) {
      return i !== index;
    })};
  });
}

ES6 एरो फ़ंक्शंस के साथ Array.prototyp.filter का उपयोग करना

removeItem(index) {
  this.setState((prevState) => ({
    data: prevState.data.filter((_, i) => i !== index)
  }));
}

अपरिवर्तनशीलता-सहायक का उपयोग करना

import update from 'immutability-helper'
...
removeItem(index) {
  this.setState((prevState) => ({
    data: update(prevState.data, {$splice: [[index, 1]]})
  }))
}

स्प्रेड का उपयोग करना

function removeItem(index) {
  this.setState((prevState) => ({
    data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
  }))
}

ध्यान दें कि प्रत्येक उदाहरण में, उपयोग की गई तकनीक की परवाह किए बिना, this.setState()कॉलबैक पारित किया जाता है, पुराने के लिए वस्तु संदर्भ नहींthis.state ;


3
यह सही उत्तर है, यह भी देखें द पावर ऑफ नॉट म्यूटिंग डेटा
विन्नी जेम्स

1
जोड़े गए विभिन्न तकनीकों के साथ प्रबल कॉलबैक का उपयोग करने वाले उदाहरण।
pscl

क्या होगा अगर मैं इसे इस तरह से करूं? this.setState({ data: [...this.state.data.slice(0, index), ...this.state.data.slice(index + 1)] }); क्या @ user1628461 द्वारा दिखाए गए कॉलबैक विकल्प के this.stateबजाय इसका उपयोग करना गलत है prevState?
तिबरियू मैक्सिम

यह सबसे अच्छा समाधान है, हालांकि सबसे सरल नहीं है
विकासशील

धन्यवाद, इसका उपयोग करने के बजाय बीच में एक तत्व को अद्यतन करने के लिए अपने संभव को फैलाने के लिए, यही मुझे चाहिए।
वैभव विशाल

24

यहां ES6 प्रसार सिंटैक्स का उपयोग करके राज्य में सरणी से तत्व को निकालने का एक तरीका है।

onRemovePerson: (index) => {
  const data = this.state.data;
  this.setState({ 
    data: [...data.slice(0,index), ...data.slice(index+1)]
  });
}

1
धन्यवाद! यह ऐसा करने का सबसे स्वाभाविक तरीका लगता है।
फेबियोमिया

3

मैं यहाँ भी झंकार करना चाहता हूँ, हालांकि इस प्रश्न का उत्तर पहले ही सही ढंग से @pscl द्वारा दिया जा चुका है यदि कोई और भी उसी मुद्दे पर चलता है जो मैंने किया था। 4 तरीकों में से मैंने एस्क फ़ंक्शंस के साथ es6 सिंटैक्स का उपयोग करने के लिए चुना है क्योंकि यह बाहरी लाइब्रेरी पर निर्भरता और निर्भरता की कमी के कारण है:

ES6 एरो फ़ंक्शंस के साथ Array.prototyp.filter का उपयोग करना

removeItem(index) {
  this.setState((prevState) => ({
    data: prevState.data.filter((_, i) => i != index)
  }));
}

आप देख सकते हैं मैं (सूचकांक के प्रकार अनदेखी करने के लिए एक मामूली संशोधन किए गए !==करने के लिए !=, क्योंकि मेरे मामले में) मैं एक स्ट्रिंग क्षेत्र से सूचकांक को पुन: प्राप्त किया गया था।

एक अन्य उपयोगी बिंदु यदि आप ग्राहक के तत्व को हटाते समय अजीब व्यवहार देख रहे हैं , तो तत्व की कुंजी के रूप में किसी सरणी के सूचकांक का उपयोग करना है :

// bad
{content.map((content, index) =>
  <p key={index}>{content.Content}</p>
)}

जब रिएक्ट एक बदलाव पर वर्चुअल डोम के साथ अलग हो जाता है, तो यह निर्धारित करने के लिए कि क्या बदल गया है, इसे देखेगा। इसलिए यदि आप सूचकांक का उपयोग कर रहे हैं और सरणी में एक कम है, तो यह पिछले एक को हटा देगा। इसके बजाय, इस तरह से सामग्री की आईडी का उपयोग करें।

// good
{content.map(content =>
  <p key={content.id}>{content.Content}</p>
)}

उपरोक्त एक संबंधित पोस्ट से इस उत्तर का एक अंश है ।

सभी को हैप्पी कोडिंग!


1

आप इस फ़ंक्शन का उपयोग कर सकते हैं, यदि आप तत्व को हटाना चाहते हैं (बिना इंडेक्स के)

removeItem(item) {
  this.setState(prevState => {
    data: prevState.data.filter(i => i !== item)
  });
}

1

जैसा कि ऊपर दिए गए एफ्रियन के जवाब के लिए एक टिप्पणी में उल्लेख किया गया है, फ़िल्टर () विशेष रूप से बड़े सरणियों के साथ धीमा हो सकता है, क्योंकि यह एक सूचकांक की तलाश में है जो पहले से निर्धारित किया गया है। यह एक साफ, लेकिन अकुशल समाधान है।

एक विकल्प के रूप में, बस वांछित तत्व को 'स्लाइस' किया जा सकता है और टुकड़े टुकड़े कर सकते हैं।

var dummyArray = [];    
this.setState({data: dummyArray.concat(this.state.data.slice(0, index), this.state.data.slice(index))})

उम्मीद है की यह मदद करेगा!


0

आप एक पंक्ति सहायक समारोह के साथ कोड को अधिक पठनीय बना सकते हैं:

const removeElement = (arr, i) => [...arr.slice(0, i), ...arr.slice(i+1)];

फिर इसे इस तरह उपयोग करें:

this.setState(state => ({ places: removeElement(state.places, index) }));

0

केवल एक सुझाव, आपके कोड में उपयोग करने के बजाय let newData = prevState.dataआप स्प्रेड का उपयोग कर सकते हैं जो ES6 में प्रस्तुत किया गया है, जिसका उपयोग आप let newData = ...prevState.data प्रतिलिपि सरणी के लिए कर सकते हैं

तीन डॉट्स ... स्प्रेड ऑपरेटर्स या रेस्ट पैरामीटर्स का प्रतिनिधित्व करता है ,

यह एक एरे एक्सप्रेशन या स्ट्रिंग या ऐसी किसी भी चीज की अनुमति देता है, जिसे उन जगहों पर विस्तारित किया जा सकता है, जहां एरे के लिए फ़ंक्शन कॉल या एलिमेंट्स के लिए शून्य या अधिक तर्क अपेक्षित हैं।

इसके अतिरिक्त, आप निम्न से सरणी से आइटम हटा सकते हैं

onRemovePerson: function(index) {
  this.setState((prevState) => ({
    data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
  }))
}

आशा है कि यह योगदान देता है !!


-3

यहाँ यह करने के लिए एक सरल तरीका है:

removeFunction(key){
  const data = {...this.state.data}; //Duplicate state.
  delete data[key];                  //remove Item form stateCopy.
  this.setState({data});             //Set state as the modify one.
}

आशा करता हूँ की ये काम करेगा!!!


समझाने की परवाह?
तिबरियू मैक्सिम

5
मुझे लगता है कि यह इसलिए है क्योंकि deleteआइटम को हटा दिया जाता है, लेकिन अनुक्रमित अपडेट नहीं होते हैं और इसलिए यह नियमित आवश्यकताओं के लिए अच्छा दृष्टिकोण नहीं होगा।
कुनोक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.