Getirme, Getirme ve Getirme Hatası Yeterli Değil – JSManifest

Getirme, Getirme ve Getirme Hatası Yeterli Değil – JSManifest

HTTP istekleri yapma hakkında okuduğumuz zaman, genellikle olağan olanı görürüz. getiriliyor, getirildiveya bir getirme hatası durum. Ardından kullanıcı arayüzü bu güncellemeyi yansıtacak şekilde güncellenmelidir. Bu üç durum, herhangi bir CRUD (Oluştur, Oku, Güncelle, Sil) işlemini yapmak için en önemli uygulamaları tanımlar.

Geliştiriciler olarak, kullanıcıyı arayüzümüzle meşgul etmekten ve mümkün olan en iyi deneyimi yaşamalarına yardımcı olmaktan sorumluyuz. Kullanıcıları müttefiklerimiz olarak görüyoruz ve istenmeyen düşmanlarımız olarak böcekler.

Örneğin veri alırken, kullanıcının bilmek onlar beklerken verileri almaya çalışıyoruz. Veriler alındığında, verileri göstermeliyiz. Bir hata oluştuğunda ve hata nesnesinde belirtilen nedenden dolayı veriler alınamadığında, kullanıcıya bir hata olduğunu bildirmeli ve hatada alınanı kullanmalıyız. Yapmak istediğimiz son şey, onları asılı bırakmaktır – tabii ki gitmelerini ve bir daha geri gelmemelerini sağlamaya çalışmadıkça.

Ama bu yeterli değil.

Yalnızca getirme durumlarına ait olması gereken değil, aynı zamanda hiç operasyon türü, özellikle CRUD operasyonları.

Zaman aşımına uğradı

Çalıştığım şirkette çok fazla HTTP isteği yapıyoruz. Karşılaştığımız en büyük sorunlardan biri, rastgele dondurulmuş Kullanıcı sayfayı yenileyene kadar bu aşamada takılıp kalan rastgele web sayfalarına döndürücüler yüklemek. Ancak bu her zaman olmaz. Ama patronum gerçekten yapmadı donmuş yükleme çarkları gibi. Bu son derece kötü bir kullanıcı deneyimiydi. Onu suçlamıyorum çünkü bu sorundan etkilenen her kullanıcı askıda kalıyor ve bazı eylemler yapmaya zorlanıyor. yapmalarını istediğimiz şeyin tam tersi.

Bunun ne olduğunu tahmin edebilir misin? Evet, doğru tahmin ettiniz. Geri düğmesine basıyorlar ve başka bir yere gidiyorlar. Tarayıcılarını kapatıyorlar ve kendilerini başka bir şeyle meşgul ediyorlar. Liste devam ediyor. Ya da olabilecek en kötü şey… geri düğmesine basıp bunun yerine bir rakibin web sitesini kullanmaya karar vermeleridir. Potansiyel bir değerli müşteriyi kaybettik. Kötü kullanıcı deneyimi, ne yazık ki örtük bir para kaybıdır :(.

Zaman aşımına uğramış bir duruma ihtiyacınız var. Sunucu yanıt vermediğinde veya herhangi bir nedenle alma durumu gönderildiğinde ve çağrı, isteği göndermeden hemen önce takıldığında (bu gerçekleşir), eklediğiniz yükleme döndürücü getiriliyor durumu dondurulur. Artık verilerin geldiğini bildirmek için kullanılan geçici bir yükleme döndürücü değil. Artık sonsuz çalışan bir yükleme çarkı ve tüm dünya asla sona geliyor. Artık bu hatayı işleme sorumluluğunu kullanıcıya geçtiniz. Geliştirici olarak başarısız oldunuz. Lütfen tekrar deneyin.

Peki bunu React’te nasıl uygularız?

gibi bazı kütüphaneler aksiyolar sağlamak zaman aşımı seçenek. Ancak bunun %100 doğru olduğuna güvenmemelisiniz. Çalıştığım şirketteki deneyimim bana bunun yeterli olmadığını ve buna çok fazla güvenmememiz gerektiğini gösterdi.

Her zamanki getirme/getirme/getirme hatası uygulamasını yapmak yerine devam edeceğiz ve bir güncelleme/güncelleme/güncelleme hatası yapacağız çünkü JavaScript’te sokağın her köşesinde “getir” ifadesini duyuyoruz.

Bu eğitim için bir özel yapacağız tepki kancası bir yöntem sağlayacak updateUser güncelleme işleyicisini çağırmak için ve içinde API çağrısı yaparken bazı eylemler gönderecektir. Ayrıca, ___ saniyeden sonra çağrılacak geçici bir zaman aşımı işlevi ayarlayacaktır.

Kanca birkaç eyalette kaydedilecektir. Bu durumlar, güncelleme işleyicisiyle birlikte arayana iletilecektir. Kanca uygulamasıyla başlayacağız ve ardından zaman aşımı bölümünü uygulayacağız.

Temel bir bileşenle başlayalım App.js ve yolumuza devam edin:

App.js

import React from 'react'
import './App.css'

const App = (props) => {
  return <div>Update Timeout</div>
}

export default App

Şimdi devam etmek ve tüm “güncelleme kullanıcı” uygulamasıyla başlamak için adında bir kanca oluşturacağız. useUpdateUser. Bu kancanın ana noktası, bir kullanıcının üzerinde bir güncelleme işlemi gerçekleştirmektir. e-posta veya şifre.

UseUpdateTimeout.js

import axios from 'axios'

const useUpdateUser = () => {
  const updateUser = async (userId, params) => {
    try {
      if (!userId) {
        throw new Error('userId is undefined')
      } else if (!params) {
        throw new Error('params is undefined')
      }
      const url = `https://someapi.com/v1/account/${userId}/`
      const response = await axios.put(url, params)
      const updatedUser = response.data
      return updatedUser
    } catch (error) {
      throw error
    }
  }

  return {
    updateUser,
  }
}

export default useUpdateUser

Şimdi kullanacağımız durumları tanımlamak için kullanımRedüktör. Kişisel olarak useReducer’ı bir tür durum kullanan hemen hemen her kancada kullanıyorum (sadece 1 durumu -_- olsa bile).

const initialState = {
  updating: false,
  updated: false,
  updateError: null,
}

Burada bir uygulamanın normal şekilde çalışması için gerekli üç durumu tanımladık. JavaScript topluluğunda, bize genellikle bir istekte hata olmadığında, hükümsüz arayanın verilerin sorunsuz bir şekilde alındığını bilmesi için hata argümanına. Yani, burada aynı standardı kullandık güncelleme hatası çünkü burada da iyi çalışıyor.

Şimdi değişiklikleri eşzamanlı durum güncellemelerine uygulamak için bir redüktör tanımlamamız gerekiyor. Redüktörler ilk durumu yansıtmalıdır:

import { useReducer } from 'react'

Ve sonra başlangıç ​​hali uygulamada redüktörü tanımlardık:

const reducer = (state, action) => {
  switch (action.type) {
    case 'updating':
      return { ...initialState, updating: true }
    case 'updated':
      return { ...initialState, updated: true }
    case 'set-error':
      return { ...initialState, updateError: action.error }
    default:
      return state
  }
}

olduğunu fark etmiş olabilirsiniz başlangıç ​​hali olağanı yaymak yerine her bir anahtar durumunda yayılıyor durum. Nedenmiş?

Bu etkili bir şekilde yapar aynı şey normalde yayılarak yazacağınız gibi durum, sadece şimdi tüm ortak kod kodunu yazmamız gerekmiyor. Gereksiz hataları ve kod boyutunu önlemek için tüm uygulamanın şu şekilde olmasını istiyoruz: basit olabildiğince. Ne zaman güncelleme geçiş yapar doğrukullanıcı arayüzü orijinal durumuna geri ayarlanmalı ve sadece önemsemek güncelleme Bölüm. Güncelleme bittiğinde ve kullanıcı profili güncellendiğinde, UI orijinal durumuna geri ayarlanmalı ve ayrıca sadece kullanıcı profilinin güncellendiğinden emin olun ( güncellenmiş devletin bir parçası). Aynı şey için de geçerli güncelleme hatası.

Aksi takdirde şöyle yazardık:

const reducer = (state, action) => {
  switch (action.type) {
    case 'updating':
      return { ...state, updated: false, updating: true }
    case 'updated':
      return { ...state, updated: true, updating: false, updateError: null }
    case 'set-error':
      return {
        ...state,
        updated: false,
        updating: false,
        updateError: action.error,
      }
    default:
      return state
  }
}

Hangi sürümü tercih edersiniz? sizi bilmem ama ben tercih ederim başlangıç ​​hali versiyon! (Birisi, initialState sürümünü kullanmanın durum güncellemelerimizin tüm gücünü ve esnekliğini ortadan kaldırdığını iddia edebilir. Kesinlikle katılıyorum, ancak buradaki eyaletler aynı amacı gerçekleştiriyor).

Şimdi yapmak istediğimiz bir sonraki şey, uygulamamızı uygulamamıza eklemektir. useUpdateTimeout kanca ile kullanımRedüktör:

UseUpdateTimeout.js

const useUpdateUser = () => {
  const [state, dispatch] = useReducer(reducer, initialState)

  const updateUser = async (userId, params) => {
    try {
      if (!userId) {
        throw new Error('userId is undefined')
      } else if (!params) {
        throw new Error('params is undefined')
      }
      const url = `https://someapi.com/v1/account/${userId}/`
      const response = await axios.put(url, params)
      const updatedUser = response.data
      return updatedUser
    } catch (error) {
      throw error
    }
  }

  return {
    updateUser,
  }
}

Ayrıca, durumlar değiştiğinde bileşenleri gerçekten güncellemeleri için onları return ifadesine yayarak arayan kişiye bu yardımcı programları sağlamak istiyoruz:

return {
  ...state,
  updateUser,
}

Şimdiye kadar, şimdi şöyle bir şeye sahibiz:

UseUpdateTimeout.js

import { useReducer } from 'react'
import axios from 'axios'

const initialState = {
  updating: false,
  updated: false,
  updateError: null,
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'updating':
      return { ...initialState, updating: true }
    case 'updated':
      return { ...initialState, updated: true }
    case 'set-error':
      return { ...initialState, updateError: action.error }
    default:
      return state
  }
}

const useUpdateUser = () => {
  const [state, dispatch] = useReducer(reducer, initialState)

  const updateUser = async (userId, params) => {
    try {
      if (!userId) {
        throw new Error('userId is undefined')
      } else if (!params) {
        throw new Error('params is undefined')
      }
      const url = `https://someapi.com/v1/account/${userId}/`
      const response = await axios.put(url, params)
      const updatedUser = response.data
      return updatedUser
    } catch (error) {
      throw error
    }
  }

  return {
    ...state,
    updateUser,
  }
}

export default useUpdateUser

Uygulamayı çağırdığımızda güncellemeKullanıcı bileşenlerin uygun şekilde güncellenmesi için sürecinden geçerken bazı eylemleri göndermesini sağlamak da iyi bir fikirdir:

const updateUser = async (userId, params) => {
  try {
    dispatch({ type: 'updating' })
    if (!userId) {
      throw new Error('userId is undefined')
    } else if (!params) {
      throw new Error('params is undefined')
    }
    const url = `https://someapi.com/v1/api/user/${userId}/`
    const response = await axios.put(url, params)
    const updatedUser = response.data
    dispatch({ type: 'updated' })
    return updatedUser
  } catch (error) {
    dispatch({ type: 'set-error', error })
  }
}

Kullanıcı arayüzü, o sırada hangi tür eylemin gönderildiğine bağlı olarak değişmelidir.

Uygulama şu anda gayet iyi çalışıyor olmalı ve orada durabiliriz. Ancak, bu gönderi bir zaman aşımına uğradı devlet, bu yüzden bundan sonra bunu uygulayacağız.

Başlangıç ​​olarak, şunu düşünmeliyiz: setZaman aşımı JavaScript’in bize sağladığı işlev. Bu, zaman aşımına uğramış bir isteğin gerçekleşmesine yardımcı olacaktır, çünkü bir istek göndermek için kullanılabilir. zaman aşımına uğradı UI bileşenlerinin dinleyebileceği eylem.

Ne zaman zaman aşımına uğradı eylem gönderilirse, kullanıcı arayüzü hemen yaptığı şeyi bırakmalı ve kendi alanında işlemin zaman aşımına uğradığını göstermelidir. Bu şekilde, kullanıcı ya internetinde bir sorun olduğunu ya da sunucuda bir sorun olduğunu bilecektir. İsteğe bağlı olarak bir yeniden denemek isteği yeniden denemek için düğmesine basın. Bunu uygulamak için başka bir eğitim yapacağım, bu yüzden biraz rehberlik arıyorsanız orada bekleyin!

Her neyse, ilan etmek istediğimiz ilk şey nerede setTimeout referansını eklemek için.

Bunun için ithal edeceğiz kullanımRef tepki vermek ve üzerine eklemek .akım useEffect bloğunun içindeki özellik:

import { useReducer, useRef } from 'react'

Kancanın içine koyarak:

const [state, dispatch] = useReducer(reducer, initialState)
const timeoutRef = useRef(null)

Ve şimdi, içinde güncellemeKullanıcı yöntem burası ilan ettiğimiz yer setZaman aşımı göndermek için geri sayıma başlama işlevi zaman aşımına uğradı zamanlayıcı ömrünün sonuna ulaşırsa eylem:

const updateUser = async (userId, params) => {
  try {
    dispatch({ type: 'updating' })
    if (!userId) {
      throw new Error('userId is undefined')
    } else if (!params) {
      throw new Error('params is undefined')
    }
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current)
    }
    timeoutRef.current = setTimeout(() => {
      dispatch({ type: 'timed-out' })
    }, 30000)
    const url = `https://someapi.com/v1/api/user/${userId}/`
    const response = await axios.put(url, params)
    clearTimeout(timeoutRef.current)
    const updatedUser = response.data
    dispatch({ type: 'updated' })
    return updatedUser
  } catch (error) {
    clearTimeout(timeoutRef.current)
    dispatch({ type: 'set-error', error })
  }
}

Nihai çıktı:

import { useReducer, useRef } from 'react'
import axios from 'axios'

const initialState = {
  updating: false,
  updated: false,
  updateError: null,
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'updating':
      return { ...initialState, updating: true }
    case 'updated':
      return { ...initialState, updated: true }
    case 'set-error':
      return { ...initialState, updateError: action.error }
    case 'timed-out':
      return { ...initialState, timedOut: true }
    default:
      return state
  }
}

const useUpdateUser = () => {
  const [state, dispatch] = useReducer(reducer, initialState)
  const timeoutRef = useRef(null)

  const updateUser = async (userId, params) => {
    try {
      dispatch({ type: 'updating' })
      if (!userId) {
        throw new Error('userId is undefined')
      } else if (!params) {
        throw new Error('params is undefined')
      }
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current)
      }
      timeoutRef.current = setTimeout(() => {
        dispatch({ type: 'timed-out' })
      }, 30000)
      const url = `https://someapi.com/v1/api/user/${userId}/`
      const response = await axios.put(url, params)
      clearTimeout(timeoutRef.current)
      const updatedUser = response.data
      dispatch({ type: 'updated' })
      return updatedUser
    } catch (error) {
      clearTimeout(timeoutRef.current)
      dispatch({ type: 'set-error', error })
    }
  }

  return {
    ...state,
    updateUser,
  }
}

export default useUpdateUser

Bu aslında şu ana kadar tamamlanmış bir uygulama gibi görünüyor! Ancak, arayanın özel bir zaman aşımı sağlamasına izin vererek daha esnek hale getirmek için kancaya biraz özelleştirme sağlamayı seviyorum:

const useUpdateUser = ({ timeout = 30000 }) => {
  const [state, dispatch] = useReducer(reducer, initialState)
  const timeoutRef = useRef(null)

  ...
}
timeoutRef.current = setTimeout(() => {
  dispatch({ type: 'timed-out' })
}, timeout)

ne olacak güncellemeKullanıcı ilk önce bir gönderiyor mu güncelleme eylem. UI bileşenleri, kullanıcının profilinin güncellenmesinden heyecan duyması için bir tür “beklemede” temsili göstermelidir. Bu yöntem yanlışlıkla çağrılırsa iki defabiz erken clearTimeout(timeoutRef.current) hemen üstünde oluyor setZaman aşımı satır, böylece yeni ayarlanmış bir öncekini kaldırabilir.

Bundan sonraki satır, setZaman aşımı astar. Bu, tüm bu gönderinin en önemli kısmı, çünkü onsuz zaman aşımı özelliği olmayacak! 🙂

Bir kere beklemek arama başarılı olursa, kullanıcının profilinin başarıyla güncellendiğini biliyoruz. Bu başarı yanıtı geldiğinde, biliyoruz ki, setZaman aşımı ifadeye artık gerek yok, bu yüzden onu siliyoruz clearTimeout(timeoutRef.current). Ve nihayet yürütmenin sonunda bir güncellenmiş başarılı profil güncellemesinin arayüze yansıtılabilmesi için eylem.

Güncelleme işlemi sırasında herhangi bir hata varsa, bir clearTimeout(timeoutRef.current) da koşuyor. Bunun nedeni, istekten gerçekten bazı yanıtlar aldığımız için, kodun gittiği yolda zaman aşımı artık göreceli değil çünkü artık yalnızca bunun yerine oluşan hatayı önemsiyoruz.

Kullanıcı Arayüzü

Bu, kancanın bu kancayla gerçek bir senaryoda uygulanmasının bir yoludur:

import React, { useState } from 'react'
import './App.css'
import useUpdateUser from './useUpdateUser'

const App = (props) => {
  const {
    updating,
    updated,
    updateError,
    timedOut,
    updateUser,
  } = useUpdateUser({
    timeout: 12000,
  })

  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const onSubmit = (e) => {
    e.preventDefault()
    const params = { email, password }
    updateUser('my-user-id123', params)
  }

  const isInitial = !updating && !updated && !updateError && !timedOut

  const errMsg =
    updateError &&
    (updateError.message || 'An error occurred. Please try again later')

  return (
    <div className='container'>
      <h2>
        {isInitial && 'Update your email or password below'}
        {updating && 'Updating your profile...'}
        {updated && 'Your profile has been updated'}
        {errMsg && <span className='error-txt'>{errMsg}</span>}
        {timedOut &&
          'We did not receive a response from the server. Please try again later'}
      </h2>
      <form onSubmit={onSubmit}>
        <div>
          <input
            type='text'
            placeholder='Email'
            name='email'
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          />
        </div>
        <div>
          <input
            type='text'
            placeholder='Password'
            name='password'
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
        </div>
        <div>
          <button type='submit'>Submit</button>
        </div>
      </form>
    </div>
  )
}

export default App

İşte uygulamanın en güzel ekran görüntüleri:

İlk Kullanıcı Arayüzü:

başlangıç-javascript

güncelleniyor

güncelleme-javascript-getirme

Güncellenmiş

güncellenmiş-javascript

Güncelleme Hatası

hata-javascript

Güncelleme Zaman Aşımı

zaman aşımı-javascript

Çözüm

İşte bizde! Bir dahaki sefere başka bir eğitim için bizi izlemeye devam edin. Ayrıca, adresinden bültenime abone olabilirsiniz. https://jsmanifest.com güncellemelerimi doğrudan gelen kutunuza almak için. onlar Bedava.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.