ลบรายการจากอาร์เรย์สถานะในการตอบสนอง


131

เรื่องราวคือฉันควรจะใส่บ็อบแซลลี่และแจ็คลงในกล่อง ฉันยังสามารถลบออกจากกล่องได้ เมื่อถอดออกไม่เหลือช่องเสียบ

people = ["Bob", "Sally", "Jack"]

ตอนนี้ฉันต้องลบพูดว่า "บ๊อบ" อาร์เรย์ใหม่จะเป็น:

["Sally", "Jack"]

นี่คือองค์ประกอบปฏิกิริยาของฉัน:

...

getInitialState: function() {
  return{
    people: [],
  }
},

selectPeople(e){
  this.setState({people: this.state.people.concat([e.target.value])})
},

removePeople(e){
  var array = this.state.people;
  var index = array.indexOf(e.target.value); // Let's say it's Bob.
  delete array[index];
},

...

ที่นี่ฉันจะแสดงโค้ดขั้นต่ำให้คุณดูเนื่องจากมีมากกว่านั้น (onClick ฯลฯ ) ส่วนสำคัญคือการลบลบทำลาย "Bob" จากอาร์เรย์ แต่removePeople()ไม่ทำงานเมื่อถูกเรียก ความคิดใด ๆ ? ฉันกำลังดูสิ่งนี้แต่ฉันอาจทำอะไรผิดพลาดเนื่องจากฉันใช้ React

คำตอบ:


170

ในการลบองค์ประกอบออกจากอาร์เรย์ให้ทำดังนี้

array.splice(index, 1);

ในกรณีของคุณ:

removePeople(e) {
  var array = [...this.state.people]; // make a separate copy of the array
  var index = array.indexOf(e.target.value)
  if (index !== -1) {
    array.splice(index, 1);
    this.setState({people: array});
  }
},

2
ในกรณีของฉันคือ: array.splice(array, 1);ขอบคุณ
Sylar

array.splice(array, 1);? ฉันเดาว่าคุณต้องแก้ไข.. คุณควรใช้ตัวแปรอื่น ...
Rayon

61
เมื่อใช้ React โดยทั่วไปคุณควรหลีกเลี่ยงการกลายพันธุ์ของคุณโดยตรง setState()คุณควรสร้างอาร์เรย์ใหม่และการใช้งาน
iaretiga

2
ฉันแนะนำให้ใช้ Array.from (this.state.items) แทนตัวดำเนินการกระจายในกรณีนี้ เนื่องจาก Array.from มีไว้สำหรับการใช้งานนี้โดยเฉพาะ
Francisco Hodge

2
ข้อเสนอแนะเล็กน้อยเพิ่มการตรวจสอบสำหรับ "ดัชนี! == -1" ก่อนที่จะเชื่อมต่ออาร์เรย์เพื่อป้องกันการลบที่ไม่ต้องการ
RoboBear

205

เมื่อใช้ React คุณไม่ควรเปลี่ยนสถานะโดยตรง หากวัตถุ (หรือArrayซึ่งเป็นวัตถุด้วย) มีการเปลี่ยนแปลงคุณควรสร้างสำเนาใหม่

มีคนอื่นแนะนำให้ใช้Array.prototype.splice()แต่วิธีนั้นทำให้ Array กลายพันธุ์ดังนั้นจึงเป็นการดีกว่าที่จะไม่ใช้splice()กับ React

ใช้ง่ายที่สุดในArray.prototype.filter()การสร้างอาร์เรย์ใหม่:

removePeople(e) {
    this.setState({people: this.state.people.filter(function(person) { 
        return person !== e.target.value 
    })});
}

42
ใช่นี่เป็นวิธีที่เปิดเผย วิธีอื่นโดยใช้ฟังก์ชัน prevState และลูกศร:this.setState(prevState => ({ people: prevState.people.filter(person => person !== e.target.value) }));
Josh Morel

9
นี่ควรเป็นคำตอบที่ได้รับการยอมรับตามสำนวน React of never mutating state
lux

9
หรือใช้ดัชนี:this.state.people.filter((_, i) => i !== index)
mb21

2
มีชิ้นที่เลียนแบบไม่ได้และประกบกันที่ไม่แน่นอน
Cassian

ปัญหาเกี่ยวกับคำตอบนี้คือหากคุณมีบุคคลหลายคนที่มีชื่อเดียวกันคุณจะลบสิ่งเหล่านี้ออกทั้งหมด การใช้ดัชนีจะปลอดภัยกว่าในกรณีที่คุณอาจมี
อาการติดตา

40

นี่คือการเปลี่ยนแปลงเล็กน้อยในการตอบสนองของ Aleksandr Petrov โดยใช้ ES6

removePeople(e) {
    let filteredArray = this.state.people.filter(item => item !== e.target.value)
    this.setState({people: filteredArray});
}

17

ใช้.spliceเพื่อลบรายการออกจากอาร์เรย์ การใช้deleteดัชนีของอาร์เรย์จะไม่ถูกเปลี่ยนแปลง แต่ค่าของดัชนีเฉพาะจะเป็นundefined

ประกบกัน ()วิธีการเปลี่ยนแปลงเนื้อหาของอาร์เรย์โดยการเอาองค์ประกอบที่มีอยู่และ / หรือการเพิ่มองค์ประกอบใหม่

ไวยากรณ์: array.splice(start, deleteCount[, item1[, item2[, ...]]])

var people = ["Bob", "Sally", "Jack"]
var toRemove = 'Bob';
var index = people.indexOf(toRemove);
if (index > -1) { //Make sure item is present in the array, without if condition, -n indexes will be considered from the end of the array.
  people.splice(index, 1);
}
console.log(people);

แก้ไข:

ตามที่ระบุไว้โดยjustin-Grantตามหลักทั่วไปอย่ากลายพันธุ์this.stateโดยตรงเนื่องจากการโทรsetState()หลังจากนั้นอาจแทนที่การกลายพันธุ์ที่คุณทำ ปฏิบัติthis.stateราวกับว่ามันไม่เปลี่ยนรูป

ทางเลือกคือการสร้างสำเนาของวัตถุในและจัดการสำเนากำหนดพวกเขากลับมาใช้this.state , ฯลฯ สามารถนำมาใช้setState()Array#mapArray#filter

this.setState({people: this.state.people.filter(item => item !== e.target.value);});

3
อย่าใช้การประกบหรือวิธีการใด ๆ ที่เปลี่ยนตัวแปรสถานะของคุณโดยตรง setStateแต่คุณจะต้องการที่จะทำสำเนาของอาร์เรย์ให้ลบรายการจากการคัดลอกและจากนั้นผ่านการคัดลอกลงใน คำตอบอื่น ๆ มีรายละเอียดเกี่ยวกับวิธีการทำเช่นนี้
Justin Grant

12

วิธีง่ายๆในการลบรายการจากอาร์เรย์สถานะในการตอบสนอง:

เมื่อข้อมูลใด ๆ ลบออกจากฐานข้อมูลและรายการอัปเดตโดยไม่มีการเรียก API ในครั้งนั้นคุณส่ง ID ที่ถูกลบไปยังฟังก์ชันนี้และฟังก์ชันนี้จะลบการกู้คืนที่ถูกลบออกจากรายการ

export default class PostList extends Component {
  this.state = {
      postList: [
        {
          id: 1,
          name: 'All Items',
        }, {
          id: 2,
          name: 'In Stock Items',
        }
      ],
    }


    remove_post_on_list = (deletePostId) => {
        this.setState({
          postList: this.state.postList.filter(item => item.post_id != deletePostId)
        })
      }
  
}


1
คุณช่วยอธิบายได้ไหมว่าสิ่งนี้แตกต่างจากคำตอบอื่น ๆ อีก 8 คำตอบสำหรับคำถามสามขวบ จากรีวิว
Wai Ha Lee

ในโค้ดด้านบนจะสร้างอาร์เรย์ข้อมูลใหม่ขึ้นมาใหม่ แต่ข้าม "deletePostId" id นี้
ANKIT-DETROJA

ใช้item.post_id !== deletePostId
Nimish goel

3

คำตอบบางคำกล่าวถึงโดยใช้ 'splice' ซึ่งทำตามที่ Chance Smith กล่าวว่าทำให้อาร์เรย์กลายพันธุ์ ฉันขอแนะนำให้คุณใช้วิธีเรียก 'slice' (เอกสารสำหรับ 'slice' อยู่ที่นี่)ซึ่งทำสำเนาของอาร์เรย์ดั้งเดิม


3

เป็นเรื่องง่ายมากก่อนอื่นคุณต้องกำหนดค่า

state = {
  checked_Array: []
}

ตอนนี้

fun(index) {
  var checked = this.state.checked_Array;
  var values = checked.indexOf(index)
  checked.splice(values, 1);
  this.setState({checked_Array: checked});
  console.log(this.state.checked_Array)
}

1

setStateคุณลืมที่จะใช้ ตัวอย่าง:

removePeople(e){
  var array = this.state.people;
  var index = array.indexOf(e.target.value); // Let's say it's Bob.
  delete array[index];
  this.setState({
    people: array
  })
},

แต่จะดีกว่าที่จะใช้filterเพราะมันไม่กลายพันธุ์อาร์เรย์ ตัวอย่าง:

removePeople(e){
  var array = this.state.people.filter(function(item) {
    return item !== e.target.value
  });
  this.setState({
    people: array
  })
},

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.