अभिक्रिया redux में लाने में त्रुटि का सबसे अच्छा तरीका क्या है?


105

मेरे पास ग्राहकों के लिए एक रिड्यूसर है, एक दूसरे के लिए AppToolbar और कुछ अन्य ...

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

लेकिन ग्राहक और AppToolbar reducers राज्य के एक ही हिस्से को साझा नहीं करते हैं और मैं reducer में एक नई कार्रवाई नहीं बना सकता।

तो मुझे वैश्विक त्रुटि दिखाने के लिए कैसे माना जाता है? धन्यवाद

अद्यतन 1:

मैं यह उल्लेख करना भूल जाता हूं कि मैं एस्टे डिस्टैक का उपयोग करता हूं

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


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

मुझे w / @ संजय से सहमत होना होगा कि इस प्रश्न के संदर्भ में कमी है। मैंने सामान्य समाधान के साथ नीचे (कोड उदाहरणों के साथ) उत्तर दिया है, लेकिन आपका प्रश्न कुछ परिशोधन का उपयोग कर सकता है। ऐसा लगता है कि आपके पास कुछ अलग मुद्दे हो सकते हैं। 1) Async क्रियाओं / त्रुटियों से निपटना। 2) अपने redux राज्य पेड़ में उचित रूप से विभाजित राज्य। 3) अपने घटकों को उस डेटा को प्राप्त करना जो उन्हें चाहिए।
एरिक अयबर

@ ErikTheDeveloper धन्यवाद, आपका जवाब बहुत अच्छा लग रहा है। लेकिन आप सही हैं, मैं संदर्भ का उल्लेख करना भूल गया। मैंने अपने प्रश्न को संपादित किया, मैं एस्टे डेस्टकैक का उपयोग कर रहा हूं और ऐसा लगता है कि आपका उत्तर वहां लागू नहीं है जैसा कि ...
दुसान प्लाव

जवाबों:


116

यदि आप "वैश्विक त्रुटियों" की अवधारणा चाहते हैं, तो आप एक errorsreducer बना सकते हैं , जो addError, removeError, आदि ... कार्यों के लिए सुन सकता है। फिर, आप अपने Redux राज्य के पेड़ पर हुक कर सकते हैं state.errorsऔर जहाँ भी उपयुक्त हो उन्हें प्रदर्शित कर सकते हैं।

ऐसे कई तरीके हैं जिनसे आप इसे प्राप्त कर सकते हैं, लेकिन सामान्य विचार यह है कि वैश्विक त्रुटियां / संदेश अपने स्वयं के reducer को <Clients />/ से पूरी तरह से अलग रहने के लिए योग्यता प्रदान करेंगे <AppToolbar />। बेशक, अगर इन घटकों में से किसी को भी आपकी आवश्यकता है, errorsतो आप errorsजहां भी जरूरत हो, उन्हें एक प्रस्ताव के रूप में पास कर सकते हैं ।

अद्यतन: कोड उदाहरण

यदि आप "वैश्विक त्रुटियों" errorsको अपने शीर्ष स्तर पर पारित करना चाहते हैं <App />और सशर्त रूप से इसे प्रस्तुत करते हैं (यदि कोई त्रुटियां मौजूद हैं) तो यह एक उदाहरण है । प्रतिक्रिया-रिड्यूक्स काconnect उपयोग <App />कुछ डेटा के लिए अपने घटक को हुक करने के लिए ।

// App.js
// Display "global errors" when they are present
function App({errors}) {
  return (
    <div>
      {errors && 
        <UserErrors errors={errors} />
      }
      <AppToolbar />
      <Clients />
    </div>
  )
}

// Hook up App to be a container (react-redux)
export default connect(
  state => ({
    errors: state.errors,
  })
)(App);

और जहां तक ​​एक्शन क्रिएटर की बात है, तो यह प्रतिक्रिया के अनुसार ( रिडक्स-थंक ) सफलता की विफलता होगी

export function fetchSomeResources() {
  return dispatch => {
    // Async action is starting...
    dispatch({type: FETCH_RESOURCES});

    someHttpClient.get('/resources')

      // Async action succeeded...
      .then(res => {
        dispatch({type: FETCH_RESOURCES_SUCCESS, data: res.body});
      })

      // Async action failed...
      .catch(err => {
        // Dispatch specific "some resources failed" if needed...
        dispatch({type: FETCH_RESOURCES_FAIL});

        // Dispatch the generic "global errors" action
        // This is what makes its way into state.errors
        dispatch({type: ADD_ERROR, error: err});
      });
  };
}

जबकि आपका reducer केवल त्रुटियों की एक सरणी का प्रबंधन कर सकता है, प्रविष्टियों को उचित रूप से जोड़ना / निकालना।

function errors(state = [], action) {
  switch (action.type) {

    case ADD_ERROR:
      return state.concat([action.error]);

    case REMOVE_ERROR:
      return state.filter((error, i) => i !== action.index);

    default:
      return state;
  }
}

1
एरिक, मैं तुम्हें यहाँ क्या सुझाव दिया है के लिए इसी तरह कुछ है लेकिन आश्चर्यजनक रूप से मैं करने के लिए प्रबंधन कभी नहीं catchकार्यों कहा जाता है, तो someHttpClient.get('/resources')या fetch('/resources')जो मैं अपने कोड बदले में उपयोग करें 500 Server Error। क्या आपके पास अपने सिर के ऊपर से कोई विचार है जहां मैं गलती कर सकता हूं? अनिवार्य रूप से, मैं fetchजो करता हूं वह एक अनुरोध भेजा जाता है जो मेरे साथ समाप्त होता है routesजिसमें मैं अपने mongooseमॉडल पर कुछ सरल करने के लिए एक विधि कहता हूं , जैसे एक पाठ जोड़ना या डीबी से एक पाठ निकालना।
केविन घबोसी

2
हे, मैं एक Google खोज से यहां आया था - बस एक महान उदाहरण के लिए धन्यवाद करना चाहता था .. मैं एक ही मुद्दे से जूझ रहा हूं, और यह शानदार है। बेशक समाधान स्टोर में त्रुटियों को एकीकृत करना है। मैंने ऐसा क्यों नहीं सोचा ...
स्पोक

2
कोई त्रुटि होने पर किसी कार्य को कैसे निष्पादित करेगा? उदाहरण के लिए मुझे UI में एक टोस्ट / अलर्ट दिखाना होगा, मूल घटक के प्रॉप्स को अपडेट करके अलर्ट घटक को रेंडर नहीं करना चाहिए
पी।

111

एरिक का जवाब सही है, लेकिन मैं यह जोड़ना चाहूंगा कि त्रुटियों को जोड़ने के लिए आपको अलग-अलग कार्रवाई नहीं करनी होगी। एक वैकल्पिक दृष्टिकोण में एक reducer है जो किसी भी errorक्षेत्र के साथ किसी भी कार्रवाई को संभालता है । यह व्यक्तिगत पसंद और सम्मेलन का मामला है।

उदाहरण के लिए, Redux real-worldउदाहरण से जिसमें त्रुटि से निपटने के लिए है:

// Updates error message to notify about the failed fetches.
function errorMessage(state = null, action) {
  const { type, error } = action

  if (type === ActionTypes.RESET_ERROR_MESSAGE) {
    return null
  } else if (error) {
    return error
  }

  return state
}

क्या इसका मतलब यह है कि हमें हर सफलता के अनुरोध पर RESET_ERROR_MESSAGE टाइप करना चाहिए।
डिमी मिकादज़े जुले

2
@DimitriMikadze नहीं यह नहीं है। यह फ़ंक्शन त्रुटियों की स्थिति के लिए सिर्फ reducer है। यदि आप RESET_ERROR_MESSAGE पास करते हैं तो यह सभी त्रुटि संदेशों को साफ कर देगा। यदि आप पास नहीं होते हैं और कोई त्रुटि क्षेत्र नहीं है, तो यह अपरिवर्तित स्थिति में वापस आ जाता है, इसलिए यदि पिछले कार्यों से कुछ त्रुटियां थीं, तो वे सफलता की कार्रवाई के बाद भी वहां मौजूद रहेंगे ....
दुसन प्लावक

मैं इस दृष्टिकोण को पसंद करता हूं क्योंकि यह अधिक प्राकृतिक इनलाइन प्रतिक्रिया के लिए अनुमति देता है क्योंकि उपभोक्ता errorएक्शन पेलोड में संलग्न होता है । धन्यवाद डैन!
माइक पेरेनॉउड

1
मैं यह कैसे काम करता है के आसपास मेरे सिर नहीं मिल सकता है। वास्तविक दुनिया के उदाहरण के अलावा, क्या आपके पास कोई अलग-थलग और दस्तावेज़ / वीडियो हैं जो इसे समझा रहे हैं? यह अधिकांश परियोजनाओं की एक बहुत महत्वपूर्ण आवश्यकता है, और मैंने इस विषय पर प्रलेखन को समझना बहुत आसान पाया है। धन्यवाद।
मैट सॉन्डर्स

6
@MattSaunders यह समझने की कोशिश करते हुए कि मैं खुद डेन द्वारा एक रिड्यूस कोर्स में आया था (उत्तर देने वाला, जो वास्तव में रेडक्स का निर्माता है), त्रुटि संदेशों को प्रदर्शित करने वाले एक सेक्शन के साथ, जो इन उत्तरों और वास्तविक दुनिया के साथ मिलकर इसे घर भेज देता है। मुझे। सौभाग्य।
अगस्टिन लाडो

2

वर्तमान में मैं कुछ विशिष्ट त्रुटियों (उपयोगकर्ता इनपुट सत्यापन) के लिए ले जा रहा हूं, मेरे उप-रेड्यूसर को एक अपवाद फेंकने के लिए है, इसे मेरे रूट रिड्यूसर में पकड़ें, और इसे एक्शन ऑब्जेक्ट में संलग्न करें। फिर मेरे पास एक Redux-saga है जो किसी त्रुटि के लिए कार्रवाई ऑब्जेक्ट का निरीक्षण करता है और उस स्थिति में त्रुटि डेटा के साथ राज्य ट्री को अपडेट करता है।

इसलिए:

function rootReducer(state, action) {
  try {
    // sub-reducer(s)
    state = someOtherReducer(state,action);
  } catch (e) {
    action.error = e;
  }
  return state;
}

// and then in the saga, registered to take every action:
function *errorHandler(action) {
  if (action.error) {
     yield put(errorActionCreator(error));
  }
}

और फिर राज्य के पेड़ में त्रुटि जोड़ना जैसा कि एरिक का वर्णन है।

मैं इसे बहुत संयम से इस्तेमाल करता हूं, लेकिन यह मुझे डुप्लिकेट तर्क रखने से रोकता है, जो वैध रूप से रिड्यूसर में है (इसलिए यह खुद को अमान्य स्थिति से बचा सकता है)।


1

सभी संबंधित संबंधित त्रुटि को संभालने के लिए कस्टम मिडलवेयर लिखें। इस स्थिति में आपका कोड अधिक क्लीनर होगा।

   failure/ error actin type ACTION_ERROR

   export default  (state) => (next) => (action) => {

      if(ACTION_ERROR.contains('_ERROR')){

       // fire error action
        store.dispatch(serviceError());

       }
}

1
इसके अलावा IMHO
क्रिस्रीली

2
आपको इसके लिए मिडलवेयर की आवश्यकता नहीं है, आप ठीक उसी ifमें लिख सकते हैं
जुआन कैम्पा

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

0

मैं जो भी कर रहा हूं वह प्रति प्रभाव के आधार पर सभी त्रुटि हैंडलिंग को केंद्रीकृत करता है

/**
 * central error handling
 */
@Effect({dispatch: false})
httpErrors$: Observable<any> = this.actions$
    .ofType(
        EHitCountsActions.HitCountsError
    ).map(payload => payload)
    .switchMap(error => {
        return of(confirm(`There was an error accessing the server: ${error}`));
    });

-8

आप axios HTTP क्लाइंट का उपयोग कर सकते हैं। इसने पहले ही इंटरसेप्टर फ़ीचर लागू कर दिया है। आप अनुरोधों या प्रतिक्रियाओं को तब तक रोक सकते हैं जब तक वे तब तक संभाले या पकड़ न लें।

https://github.com/mzabriskie/axios#interceptors

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });


हां लेकिन आप रिडक्स के लिए कुछ भी नहीं भेज रहे हैं?
Eino Mäkitalo

यह दृष्टिकोण बुरा नहीं है। आमतौर पर Redux में स्टोर एक सिंगलटन है और आप अपने कार्यों को ट्रिगर करने के लिए axios इंटरसेप्टर फ़ाइल में स्टोर आयात कर सकते हैं और store.dispatch () का उपयोग कर सकते हैं। यह सिस्टम में सभी एपी त्रुटियों को 1 स्थान पर संभालने के लिए एकात्मक दृष्टिकोण है
वेमिच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.