Wyświetlanie wyników pracy thunk w komponencie w Reduksie
Na poprzednich zajęciach wysłaliśmy żądanie POST
za pomocą thunk addProduct. Teraz
wyświetlimy wyniki jego pracy w komponencie.
Otwórzmy naszą aplikację z produktami, a w
niej plik NewProductForm.jsx, ponieważ ten
komponent jest odpowiedzialny za dodawanie nowego
produktu. Spójrzmy na linie z importami.
Zamieńmy import akcji productAdded, na
import thunk addProduct:
import { addProduct } from './productsSlice'
Teraz, ponieważ nie śledzimy w slice'ie
statusu 'pending' żądania, zróbmy tak,
aby użytkownik mógł kliknąć przycisk
zapisania produktu tylko raz, ponieważ
nie potrzebujemy tych samych powtórnych żądań.
W tym celu utwórzmy kolejny stan lokalny:
const [requestStatus, setRequestStatus] = useState('idle')
Następnie po obsługach i przed funkcją
onSaveProductClick napiszmy kod, w którym
sprawdzimy, czy wszystkie pola formularza są wypełnione
i czy status żądania jest w 'idle':
const canBeSaved =
[name, desc, price, amount, sellerId].every(Boolean) &&
requestStatus === 'idle'
Następnie zmienimy kod dla onSaveProductClick. Po pierwsze
będzie to funkcja asynchroniczna i będzie wykonywana,
jeśli prawdziwy jest powyższy warunek:
const onSaveProductClick = async () => {
if (canBeSaved) {}
}
Pomimo że w slice'ie nie śledzimy statusu
'rejected', i tak możemy wyświetlić w
konsoli błąd, w tym celu użyjemy
konstrukcji try-catch.
Tutaj dodamy również finally,
aby po wykonaniu żądania ponownie ustawić
stan lokalny na 'idle':
const onSaveProductClick = async () => {
if (canBeSaved) {
try {
} catch (err) {
console.error('błąd zapisu produktu: ', err)
} finally {
setRequestStatus('idle')
}
}
}
Z blokami catch i finally się uporaliśmy, napiszmy
kod dla bloku try. Tutaj ustawimy lokalny
status na 'in pogress', dopóki nie wróci
jakaś odpowiedź w wyniku pracy thunk,
następnie wyślemy nasz thunk addProduct. Użycie
konstrukcji try-catch w zależności
od typu odpowiedzi pomoże nam funkcja RTK unwrap,
którą ona dodaje do zwracanej obietnicy.
Następnie, jeśli żądanie zakończyło się sukcesem, ustawiamy
stany lokalne na ich początkowe wartości. Pełny
kod dla onSaveProductClick będzie wyglądać tak:
const onSaveProductClick = async () => {
if (canBeSaved) {
try {
setRequestStatus('in progress')
await dispatch(
addProduct({ name, desc, price, amount, seller: sellerId })).unwrap()
setName('')
setDesc('')
setPrice(0)
setAmount(0)
setSellerId('')
} catch (err) {
console.error('błąd zapisu produktu: ', err)
} finally {
setRequestStatus('idle')
}
}
}
Uruchommy naszą aplikację i spróbujmy dodać nowy produkt. Jak widzicie, w przypadku udanego żądania pola są czyszczone i nowy produkt jest dodawany do listy produktów. Zajrzyjcie również w przeglądarce do Redux DevTools i przejdźcie po jego zakładkach, przyjrzyjcie się akcjom i temu, jak zmienia się wasz stan.
Otwórz twoją aplikację ze studentami.
Otwórz w niej plik NewStudentForm.jsx.
Dodaj kolejny stan lokalny requestStatus,
i ustaw go początkowo na 'idle'.
Zapoznawszy się z materiałami lekcji, utwórz
zmienną canBeSaved, za pomocą której
przycisk zapisywania nowych danych studenta będzie
działał/nie działał, w zależności od wartości
requestStatus i od wypełnienia pól.
Napisz asynchroniczny kod dla onSaveStudentClick,
który będzie zmieniał wartość requestStatus
w zależności od sytuacji, wysyłał thunk addProduct
z danymi nowego studenta, czyścił pola
w przypadku udanego żądania i wyświetlał w
konsoli błąd w przypadku niepowodzenia,
jak pokazano w lekcji. Użyj do tego
konstrukcji try-catch i funkcji RTK
unwrap.
Uruchom twoją aplikację, dodaj nowego studenta i upewnij się, że wszystko działa.