ค้นหาเว็บไซต์

javascript - นี่คือวิธีที่ถูกต้องในการลบไอเท็มโดยใช้ redux หรือไม่?


ฉันรู้ว่าฉันไม่ควรแก้ไขข้อมูลนำเข้าโดยตรงและควรทำการโคลนวัตถุเพื่อแก้ไข ฉันกำลังปฏิบัติตามแนวทางที่ใช้ในโปรเจกต์เริ่มต้นของ Redux ที่ใช้:

ADD_ITEM: (state, action) => ({
  ...state,
  items: [...state.items, action.payload.value],
  lastUpdated: action.payload.date
})

สำหรับการเพิ่มรายการ - ฉันเข้าใจการใช้ spread เพื่อเพิ่มรายการในอาร์เรย์แล้ว

สำหรับการลบ ฉันใช้:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: [...state.items.splice(0, action.payload), ...state.items.splice(1)],
  lastUpdated: Date.now() 
})

แต่นี่กำลังเปลี่ยนแปลงวัตถุ state ของอินพุต - สิ่งนี้ห้ามหรือเปล่าแม้ว่าฉันจะส่งคืนวัตถุใหม่?

คำตอบ #1

ไม่เคย เปลี่ยนแปลงสถานะของคุณ

แม้ว่าคุณจะกำลังส่งกลับอ็อบเจ็กต์ใหม่ คุณก็ยังคงปนเปื้อนอ็อบเจ็กต์เก่า ซึ่งคุณไม่ต้องการทำเลย นี่ทำให้เกิดปัญหาเมื่อทำการเปรียบเทียบระหว่างสถานะเก่าและสถานะใหม่ ตัวอย่างเช่น ใน shouldComponentUpdate ที่ react-redux ใช้ภายใต้ระบบเบื้องหลัง นอกจากนี้ยังทำให้การเดินทางข้ามเวลาที่ผ่านมาเป็นไปไม่ได้ (เช่น การเลิกทำและทำซ้ำ)

แทนที่จะใช้เช่นนั้น ให้ใช้วิธีการที่ไม่เปลี่ยนแปลงเสมอ ใช้ Array#slice เสมอและอย่าใช้ Array#splice

จากโค้ดของคุณ ฉันสันนิษฐานว่า action.payload คือดัชนีของรายการที่กำลังถูกลบ วิธีที่ดีกว่าคือดังนี้:

items: [
    ...state.items.slice(0, action.payload),
    ...state.items.slice(action.payload + 1)
],

คำตอบ #2

คุณสามารถใช้วิธี filter ของอาร์เรย์เพื่อลบองค์ประกอบเฉพาะออกจากอาร์เรย์โดยไม่ทำให้สถานะเดิมเปลี่ยนแปลง

return state.filter(element => element !== action.payload);

ในบริบทของโค้ดของคุณ มันจะดูเหมือนประมาณนี้:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: state.items.filter(item => item !== action.payload),
  lastUpdated: Date.now() 
})

คำตอบ #3

เมธอด Array.prototype.filter ของ ES6 จะคืนค่าอาร์เรย์ใหม่ที่มีรายการที่ตรงตามเกณฑ์ ดังนั้น ในบริบทของคำถามเดิม สิ่งนี้จะเป็น:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: state.items.filter(item => action.payload !== item),
  lastUpdated: Date.now() 
})

คำตอบ #4

อีกหนึ่งรูปแบบของตัวลดค่า "DELETED" ที่ไม่เปลี่ยนแปลงสำหรับอาเรย์ที่มีวัตถุ:

const index = state.map(item => item.name).indexOf(action.name);
const stateTemp = [
  ...state.slice(0, index),
  ...state.slice(index + 1)
];
return stateTemp;

บทความที่เกี่ยวข้อง