React redux'te bir getirme hatasıyla başa çıkmanın en iyi yolu nedir?


105

Müşteriler için bir redüktörüm var, bir tane de AppToolbar için ve diğerleri ...

Şimdi, istemciyi silmek için bir getirme eylemi oluşturduğumu ve başarısız olursa İstemciler indirgeyicisinde bazı şeyler yapması gereken bir kodum olduğunu ve ayrıca AppToolbar'da bazı genel hatalar görüntülemek istediğimi varsayalım.

Ancak İstemciler ve AppToolbar redüktörleri devletin aynı bölümünü paylaşmıyor ve redüktörde yeni bir hareket oluşturamıyorum.

Öyleyse küresel hatayı nasıl göstereceğim? Teşekkürler

GÜNCELLEME 1:

Ben kullanmak belirtmeyi unutmayın este devstack

GÜNCELLEME 2: Eric'in cevabını doğru olarak işaretledim, ancak este'de kullandığım çözümün daha çok Eric ve Dan'in cevabının kombinasyonu gibi olduğunu söylemeliyim ... Kodunuzda size en uygun olanı bulmanız yeterli .. .


2
Yakın oylar alıyorsunuz ve bunun nedeni muhtemelen çok fazla örnek kod sağlamamış olmanızdır. Sorunuz ve aldığınız yanıtlar, sorun daha açık bir şekilde ana hatlarıyla belirtilirse diğer insanlara daha yardımcı olacaktır.
acjay

Bu sorunun bağlamda eksik olduğu konusunda @acjay ile aynı fikirdeyim. Aşağıda (kod örnekleriyle) genel bir çözümle yanıt verdim, ancak sorunuz biraz ayrıntılandırma gerektirebilir. Görünüşe göre birkaç ayrı sorununuz olabilir. 1) Eşzamansız eylemleri / hataları işleme. 2) Redux durum ağacınızda durumu uygun şekilde bölme. 3) Bileşenlerinize ihtiyaç duydukları verileri almak.
Erik Aybar

@ErikTheDeveloper teşekkürler, cevabınız harika görünüyor. Ama haklısın, bağlamdan bahsetmeyi unuttum. Sorumu düzenledim, este devstack kullanıyorum ve görünüşe göre cevabınız orada olduğu gibi geçerli değil ...
Dusan Plavak

Yanıtlar:


116

"Genel hatalar" konseptine sahip olmak istiyorsanız errors, addError, removeError, vb. Eylemlerini dinleyebilen bir indirgeyici oluşturabilirsiniz . Ardından, adresinde Redux eyalet ağacınıza bağlanabilir state.errorsve bunları uygun olan her yerde görüntüleyebilirsiniz.

Orada bu yaklaşım olabilir birçok yolu vardır, ama genel bir fikir küresel hatalar / mesajlar tamamen ayrı yaşamak için kendi düşürücü hak olduğunu ifade etti <Clients />/ ' <AppToolbar />. Elbette, bu bileşenlerden herhangi birinin erişmesi gerekiyorsa, ihtiyaç duyduğunuz her yerde bir destek olarak onlara errorsgeçebilirsiniz errors.

Güncelleme: Kod Örneği

Burada, "genel hataları" errorsen üst seviyenize <App />geçirip koşullu olarak işlediğinizde (mevcut hatalar varsa) nasıl görünebileceğine dair bir örnek verilmiştir . Bileşeninizi bazı verilere bağlamak için react-redux'lericonnect kullanma <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);

Ve eylem yaratıcısı söz konusu olduğunda, yanıta göre ( redux-thunk ) başarı başarısızlığı gönderir.

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});
      });
  };
}

Düşürücünüz, girişleri uygun şekilde ekleyip / kaldırarak bir dizi hatayı yönetebilir.

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
Erik, burada önerdiğine benzer bir şeyim var ama şaşırtıcı bir şekilde , kod dönüşümde catchkullansam someHttpClient.get('/resources')ya fetch('/resources')da kullanırsam adı verilen işlevleri almayı asla başaramam 500 Server Error. Yanlış yapabileceğim bir düşüncen var mı? Esasen, yaptığım şey, bir metin eklemek veya DB'den bir metni kaldırmak gibi çok basit bir şey yapmak için modelimde bir yöntem çağırdığım bir yöntemle fetchsonuçlanan bir istek göndermek . routesmongoose
Kevin Ghaboosi

2
Hey, buraya bir Google aramasından geldim - sadece harika bir örnek için teşekkür etmek istedim .. Aynı sorunlarla uğraşıyorum ve bu harika. Elbette çözüm, hataları mağazaya entegre etmektir. Neden bunu düşünmedim ... şerefe
Spock

2
Bir hata oluştuğunda bir kişi bir işlevi nasıl yürütür? Örneğin, kullanıcı arayüzünde bir uyarı / uyarı göstermem gerekiyor, ana bileşenin props'larını güncelleyerek bir Uyarı bileşeni oluşturmamalıyım
Gianfranco

111

Erik'in cevabı doğru, ancak eklemek isterim ki, hata eklemek için ayrı eylemler yapmak zorunda değilsiniz. Alternatif bir yaklaşım, bir erroralanla herhangi bir eylemi gerçekleştiren bir azaltıcıya sahip olmaktır . Bu kişisel bir seçim ve konvansiyon meselesidir.

Örneğin , hata işleme içeren Redux real-worldörneğinden :

// 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
}

Her başarı isteğinde RESET_ERROR_MESSAGE türünü errorMessage düşürücüye geçirmemiz gerektiği anlamına mı geliyor?
Dimi Mikadze

2
@DimitriMikadze hayır öyle değil. Bu fonksiyon sadece hata durumu için indirgeyicidir. RESET_ERROR_MESSAGE'ı geçerseniz, tüm hata mesajlarını temizleyecektir. Geçmezseniz ve hata alanı yoksa, sadece değişmemiş duruma geri döner, yani önceki eylemlerden bazı hatalar varsa, başarılı eylemden sonra hala orada olacaklardır ....
Dusan Plavak

Bu yaklaşımı tercih ediyorum çünkü tüketici erroreylem yükünü ekledikçe daha doğal bir satır içi tepkiye izin veriyor . Teşekkürler Dan!
Mike Perrenoud

1
Bunun nasıl çalıştığını tam olarak anlayamıyorum. Gerçek dünya örneğinin dışında, bunu açıklayan herhangi bir izole belgeniz ve belgeniz / videonuz var mı? Bu, çoğu projenin oldukça temel bir gereksinimidir ve konuyla ilgili belgeleri anlaşılması çok az kolay buldum. Teşekkürler.
Matt Saunders

6
@MattSaunders Bunu anlamaya çalışırken, Dan'in kendisinin (cevaplayıcı, aslında Redux'un yaratıcısı) bir Redux kursuna rastladım , bu cevaplarla ve gerçek dünya örneğiyle birlikte onu eve götüren Hata Mesajlarını Görüntüleme üzerine bir bölümle karşılaştım. ben mi. İyi şanslar.
Agustín Lado

2

Şu anda birkaç özel hata (kullanıcı girişi doğrulaması) için uyguladığım yaklaşım, alt indirgeyicilerimin bir istisna atmasını, bunu kök azaltıcımda yakalamasını ve eylem nesnesine eklemesini sağlamaktır. Sonra eylem nesnelerini bir hata açısından inceleyen ve bu durumda durum ağacını hata verileriyle güncelleyen bir redux-destanım var.

Yani:

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));
  }
}

Ve sonra hatayı durum ağacına eklemek Erik'in tarif ettiği gibi.

Oldukça idareli kullanıyorum, ancak yasal olarak indirgeyiciye ait olan mantığı kopyalamak zorunda kalmamı engelliyor (böylece kendini geçersiz bir durumdan koruyabilir).


1

API ile ilgili tüm hataların üstesinden gelmek için özel bir Ara Yazılım yazın. Bu durumda kodunuz daha temiz olacaktır.

   failure/ error actin type ACTION_ERROR

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

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

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

       }
}

1

2
Bunun için ara katman yazılımına ihtiyacınız yok, aynısını ifbir indirgeyiciye yazabilirsiniz
Juan Campa

50'den fazla API varsa, her yerde yazmanız gerekir. Bunun yerine, hatayı kontrol etmek için özel bir ara yazılım yazabilirsiniz.
Shrawan

0

Yaptığım şey, etkideki tüm hata işlemeyi etki başına esasına göre merkezileştirmek

/**
 * 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 istemcisini kullanabilirsiniz. Durdurucular özelliği zaten uygulanmıştır. İstekleri veya yanıtları, o zamana kadar ele alınmadan veya yakalamadan önce yakalayabilirsiniz.

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);
  });


Evet ama yeniden düzenlemeye hiçbir şey göndermiyor musunuz?
Eino Mäkitalo

Bu yaklaşım fena değil. Genellikle redux'ta saklamak tek bir işlemdir ve depolamayı axios durdurucular dosyasında içe aktarabilir ve herhangi bir eylemi tetiklemek için store.dispatch () kullanabilirsiniz. Bu, sistemdeki tüm API hatalarını tek bir yerde ele almak için tek bir yaklaşımdır
34'te Çar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.