ตัวรีดิวเซอร์เพิ่มเติมใน Redux
ลองเปิดแอปพลิเคชันผลิตภัณฑ์ของเรา
และไฟล์ productsSlice.js ภายในนั้น คุณอาจจะ
สังเกตเห็นว่าเราสร้าง thunk fetchProducts
เป็นฟังก์ชันแยกต่างหาก? เราทำแบบนั้นเพราะ
createSlice ไม่รองรับการนิยาม
thunks แล้วเราจะทำให้
reducer ของ slice products ตอบสนองต่อแอ็กชัน
ที่ถูกนิยามไว้นอกเหนือจาก products ได้อย่างไร?
เพราะเราต้องการจัดการแอ็กชัน
ที่ส่งโดย thunk fetchProducts พอดี
สำหรับกรณีเช่นนี้ createSlice มี
คุณสมบัติ extraReducers ซึ่งอนุญาตให้
เพิ่ม ตัวรีดิวเซอร์เพิ่มเติม ซึ่ง
จะทำหน้าที่จัดการแอ็กชัน
ที่ไม่ได้ถูกนิยามไว้ใน slice นี้
ตอนนี้ภายในฟังก์ชัน createSlice
หลังคุณสมบัติ reducers ที่มีตัวรีดิวเซอร์ทั้งหมด
ให้เพิ่มเมธอดอีกหนึ่งตัวคือ extraReducers:
extraReducers() {},
เรา必須ส่ง object
builder ให้กับเมธอดนี้
ซึ่งมีเมธอดที่ใช้สำหรับเพิ่ม
ตัวรีดิวเซอร์เพิ่มเติม:
extraReducers(builder) {},
เราจะใช้หนึ่งในเมธอดของ builder -
addCase ซึ่งรับพารามิเตอร์แรกเป็น
action creator และพารามิเตอร์ที่สองเป็น reducer แอ็กชันหนึ่ง
ที่ fetchProducts จะส่งเมื่อมีการร้องขอคือ
fetchProducts.pending ซึ่งบอกเรา
ว่าการร้องขอถูกส่งแล้ว ใน
กรณีนี้เราจะเปลี่ยนสถานะเป็น 'in progress'
(ก่อนหน้านี้เป็น 'idle'):
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
ตอนนี้มาจัดการแอ็กชันที่จะถูกส่ง
ในกรณีที่การร้องขอสำเร็จ ที่นี่เราจะ
เปลี่ยนไม่เพียงแต่สถานะใน state เป็น
'success' แต่ยังดึงข้อมูลผลิตภัณฑ์มาไว้ใน
slice products จาก payload ของแอ็กชัน
เพื่อรวบรวมผลิตภัณฑ์ทั้งหมด เราต้องการ
เมธอด concat:
extraReducers(builder) {
builder
.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
.addCase(fetchProducts.fulfilled, (state, action) => {
state.status = 'success'
state.products = state.products.concat(action.payload)
})
},
ในกรณีที่การร้องขอไม่สำเร็จ เราจะเปลี่ยน
สถานะเป็น 'fail' และบันทึกลงใน state
ข้อความแสดงข้อผิดพลาด:
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
ถ้าเราเปิดแอปพลิเคชันของเราตอนนี้
และคลิกที่ 'Products' ในเมนู แล้ว
ผ่านไปสองสามวินาที (จำดีเลย์
ที่เราตั้งไว้บนเซิร์ฟเวอร์ได้ไหม?) เราจะเห็น
รายการผลิตภัณฑ์
เราจะเห็นการเปลี่ยนแปลงใน Redux
DevTools เช่นเดียวกัน ตอนนี้ผลิตภัณฑ์ของเราจะปรากฏใน
state (ดูที่แท็บ 'State')
ถ้าคุณคลิกที่แอ็กชัน
products/fetchProducts/fulfilled
สถานะใหม่ 'success' ก็จะปรากฏเช่นกัน
ตอนนี้คลิกที่แอ็กชัน
products/fetchProducts/pending และดู
ว่าแท็บ 'State' แตกต่างกันอย่างไร
ปัญหาเดียวที่อาจเกิดขึ้นกับคุณ
(ฉันเคยพูดถึงเรื่องนี้
ในบทเรียนที่แล้ว) - นั่นคือการทำซ้ำ
ของการร้องขอข้อมูล ส่งผลให้ใน
รายการของเราไม่ได้มี 8 แต่มีถึง
16 รายการ และมีการแจ้งเตือนระดับร้ายแรง
ในคอนโซลนักพัฒนา มาลอง
แก้ไขปัญหานี้ในบทเรียนถัดไป
เปิดแอปพลิเคชันนักเรียนของคุณ
เปิดไฟล์ studentsSlice.js ในนั้น ภายใน
ฟังก์ชัน createSlice หลังคุณสมบัติ
reducers ให้เพิ่มคุณสมบัติ extraReducers
ส่ง builder ให้กับเมธอด extraReducers
ใช้เมธอด builder.addCase
เพิ่มการจัดการสำหรับแอ็กชัน pending,
fulfilled และ rejected ซึ่ง
ถูกส่งโดย fetchStudents เมื่อร้องขอ
ข้อมูล ตามที่แสดงในบทเรียน