จะเรียกใช้การโทรกลับหลังจากอัปเดตสถานะใน Redux ได้อย่างไร


86

setState(state, callback)ในการตอบสนองของรัฐไม่ได้มีการปรับปรุงทันทีดังนั้นเราจึงสามารถใช้โทรกลับใน แต่จะทำอย่างไรใน Redux?

หลังจากโทรไปthis.props.dispatch(updateState(key, value))ฉันต้องทำอะไรบางอย่างกับสถานะที่อัปเดตทันที

มีวิธีใดบ้างที่ฉันสามารถโทรกลับด้วยสถานะล่าสุดเหมือนกับสิ่งที่ฉันทำใน React


คุณใช้thunk?
Pranesh Ravi

1
ฉันคิดว่าdispatch()เป็นกิจกรรมซิงโครนัส สถานะที่อัปเดตควรพร้อมใช้งานในบรรทัดถัดไป
Pranesh Ravi

4
@PraneshRavi ฉันคิดอย่างนั้น แต่ฉันมีสถานะเก่า ฉันไม่ได้ใช้thunk.
Brick Yang


1
ใช่การจัดส่งเป็นแบบซิงโครนัส แต่การอัปเดตอุปกรณ์ประกอบฉากในภายหลังไม่ใช่ ดังนั้นสถานะ redux จึงถูกอัปเดตในบรรทัดถัดไป แต่อุปกรณ์ประกอบฉากของคอมโพเนนต์ยังไม่มี
amik

คำตอบ:


113

ควรอัปเดตส่วนประกอบเพื่อรับอุปกรณ์ประกอบฉากใหม่

มีหลายวิธีในการบรรลุเป้าหมายของคุณ:

1. componentDidUpdateตรวจสอบว่ามีการเปลี่ยนแปลงค่าหรือไม่จากนั้นทำบางสิ่ง ..

 componentDidUpdate(prevProps){
     if(prevProps.value !== this.props.value){ alert(prevProps.value) }
  }

2. redux-สัญญา (มิดเดิลแวร์จะส่งค่าที่แก้ไขแล้วของสัญญา)

export const updateState = (key, value)=>
Promise.resolve({
  type:'UPDATE_STATE',
  key, value
})

จากนั้นในส่วนประกอบ

this.props.dispatch(updateState(key, value)).then(()=>{
   alert(this.props.value)
})

2. redux-thunk

export const updateState = (key, value) => dispatch => {
  dispatch({
    type: 'UPDATE_STATE',
    key,
    value,
  });
  return Promise.resolve();
};

จากนั้นในส่วนประกอบ

this.props.dispatch(updateState(key, value)).then(()=>{
   alert(this.props.value)
})

6
ในredux-thunkตัวอย่างของคุณคุณใช้dispatchราวกับว่ามันเป็นซิงโครนัส เป็นอย่างนั้นหรือ?
Danny Harding

2
@DannyHarding dispatchไม่ซิงโครนัส โดยไม่ต้องPromise.resolve(), this.props.valueยังคงกลับค่าเดิม ยังคงจำเป็นต้องมีการเลื่อนแบบ async บางประเภท (การอ้างอิงจากภายใน a setTimeoutก็ใช้ได้เช่นกัน)
Drazen Bjelovuk

4
@DrazenBjelovuk ฉันสงสัยเพราะฟังก์ชัน updateState ในตัวอย่าง redux-thunk มีการจัดส่ง (someAction) ทันทีตามด้วย return Promise.resolve () คำสัญญาจะแก้ไขทันทีซึ่งฉันคิดว่าจะสร้างเงื่อนไขการแข่งขันระหว่างการอัปเดตร้านค้า redux และ. จากนั้นเรียกในส่วนประกอบ เนื่องจากการจัดส่งไม่ส่งคืนสัญญาหรือยอมรับการติดต่อกลับฉันไม่คิดว่านี่เป็นวิธีที่ถูกต้องในการทราบว่าเมื่อใดที่ร้านค้า redux ได้รับการอัปเดต ฉันคิดว่าคำตอบของ just-boris ถูกต้องในกรณีนี้
Danny Harding

2
@DannyHarding ใช่ฉันยอมรับว่าวิธีนี้ไม่น่าจะเป็นการรับประกันไฟที่แน่นอนเพียงแค่แสดงให้เห็นว่าการจัดส่งไม่ซิงโครนัส
Drazen Bjelovuk

1
ฉันพยายามใช้โซลูชัน redux-thunk ที่นี่ แต่ฉันได้รับTypeError: _this.props.dispatch is not a function?
Krillko

14

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

คุณไม่ควรคิดเช่น "ฉันไม่ได้Aตอนนี้Xกลายเป็นYและฉันจัดการกับมัน" แต่ "ฉันจะทำอย่างไรเมื่อXกลายเป็นY" Aโดยไม่มีความสัมพันธ์ใด สถานะร้านค้าสามารถอัปเดตได้จากแหล่งที่มาหลายแหล่งนอกจากส่วนประกอบของคุณแล้วการเดินทางข้ามเวลายังสามารถเปลี่ยนสถานะและจะไม่ถูกส่งผ่านAจุดจัดส่งของคุณ

โดยทั่วไปหมายความว่าคุณควรใช้componentWillReceivePropsตามที่ @Utro เสนอ


นี่คือคำตอบที่ op กำลังมองหาอยู่จริงๆ (แม้ว่าดูเหมือนว่าเขาจะไม่รู้เรื่องนี้
ก็ตาม

1
ฉันเห็นด้วย แต่ดูเหมือนว่าจะถือเป็นการต่อต้านรูปแบบ
Giacomo Cerquone

1
เราจะทำอย่างไรที่componentWillReceivePropsเลิกใช้แล้ว static getDerivedStateFromProps()ดูเหมือนจะไม่เป็นการทดแทนที่เหมาะสมเนื่องจากไม่สามารถโทรกลับได้เท่าที่ฉันสามารถบอกได้
M3RS

9

ด้วย Hooks API:

useEffect โดยมีเสาเป็นอินพุต

import React, { useEffect} from 'react'
import { useSelector } from 'react-redux'

export default function ValueComponent() {
   const value = useSelector(store => store.pathTo.value)

   useEffect(() => {
     console.log('New value', value) 
     return () => {
        console.log('Prev value', value) 
     }

   }, [value])

   return <div> {value} </div>
}

คำตอบที่ยอมรับได้เขียนไว้ก่อน React Hooks นี่ควรเป็นคำตอบที่ได้รับการยอมรับในตอนนี้หลังจากการแนะนำตะขอ เป็นวิธีที่มีปฏิกิริยามากขึ้นในการจัดการกับการเปลี่ยนแปลง
TIF

5

คุณสามารถใช้subscribeListener และจะถูกเรียกเมื่อมีการส่งการดำเนินการ ภายในเครื่องฟังคุณจะได้รับข้อมูลร้านค้าล่าสุด

http://redux.js.org/docs/api/Store.html#subscribelistener


2
subscribeจะเริ่มทำงานเมื่อมีการส่งการดำเนินการเท่านั้น ไม่มีทางที่subscribeจะแจ้งให้คุณทราบได้ว่าการเรียก API ของคุณส่งคืนข้อมูลหรือไม่ .. ฉันคิดว่า! : D
Mihir

คุณสามารถส่งการดำเนินการอื่นเมื่อคำขอของคุณสำเร็จ (สำเร็จหรือไม่สำเร็จ)
Jam

ฉันไม่มั่นใจว่าวิธีแก้ปัญหาอื่น ๆ ที่เสนอที่นี่ใช้งานได้จริงเพราะฉันไม่เห็นวิธีที่สัญญาว่าจะแก้ไขหรือเรียกกลับเพื่อเริ่มการทำงานหลังจากที่มีการอัปเดตสถานะแล้ว วิธีนี้ได้รับการเรียกร้องสำหรับการอัปเดตร้านค้าทุกครั้งไม่ใช่แค่วิธีที่เกิดขึ้นหลังจากเหตุการณ์ของคุณ แต่ไม่ควรแก้ไขยากเกินไป โดยเฉพาะอย่างยิ่งลิงก์ที่เขียนยูทิลิตี้สังเกตการณ์ Store ที่กำหนดเองจากหน้าที่คุณเชื่อมโยงไปนั้นมีประโยชน์มาก
Nat Kuhn

ไม่พบหน้าลิงก์
Bharat Modi

2

คุณสามารถใช้ thunk กับการโทรกลับ

myThunk = cb => dispatch =>
  myAsyncOp(...)
    .then(res => dispatch(res))
    .then(() => cb()) // Do whatever you want here.
    .catch(err => handleError(err))

สมบูรณ์แบบสำหรับสิ่งที่ฉันต้องการ!
JSON C11

-1

เป็นวิธีง่ายๆที่คุณสามารถใช้ได้: redux-สัญญา

แต่ถ้าคุณใช้redux-thunkคุณควรทำเช่นนี้:

function addCost(data) {
  return dispatch => {
    var promise1 = new Promise(function(resolve, reject) {
      dispatch(something);
     });
    return promise1;
  }
}

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