React: Do czego służy useCallback?

Opublikowano: - tagi:

Kiedy użyć useCallback?

useCallback to hook, który pozwala na usprawnienie wydajności Twojej aplikacji. Konkretnie chodzi o mądre zarządzanie funkcjami używanymi przez komponent.

Za każdym razem, kiedy komponent jest renderowany, wszystkie funkcje są tworzone na nowo. Dzieje się tak na przykład przy zmianie stanu komponentu. Po co za każdym razem tworzyć funkcję na nowo? Nie lepiej robić to w przypadku, gdy to jest naprawdę konieczne? Można to zrobić za pomocą useCallback.

Działa to, w taki sposób, że useCallback zapamiętuje daną funkcję i trzyma ją w pamięci cache. A Ty określasz, kiedy dana funkcja być ponownie stworzona.

Składnia useCallback

Jeśli używałeś wcześniej useEffect składnia useCallback jest podobna:

const someFunction = useCallback(() => {
...
}, []);

W pierwszym parametrze przekazujesz funkcję, którą chcesz trzymać w pamięci cache.

Drugi parametr to tablica zależności. Określasz tutaj listę wartości, które React ma śledzić. Jeśli dana wartość się zmieni useCallback powinien stworzyć funkcję na nowo. Jeśli przekażesz pustą tablicę, funkcja zostanie stworzona tylko raz.

Jeśli działanie Twojej funkcji zależy od danej zmiennej powinieneś ją umieścić w tablicy zależności.

Przykład użycia useCallback

import React, {useCallback, useState} from 'react';

const App = () => {
    const [taxpayerName, setTaxPayerName] = useState('');
    const [taxValue, setTaxValue] = useState(0);
    const [salary, setSalary] = useState(0);
    const [taxRate, setTaxRate] = useState(12);

    const onCalculateTax = useCallback(() => {
        setTaxValue(salary * (taxRate / 100));
    }, [salary, taxRate]);

    return (
        <>
            {
                taxpayerName &&
                <div>
                    The taxpayer: <strong>{taxpayerName}</strong> must pay <strong>{taxValue}</strong>
                </div>
            }
            <div>
                <label htmlFor="taxpayerName">Taxpayer name</label>
                <input type="text" id="taxpayerName" value={taxpayerName} onChange={(e) => setTaxPayerName(e.target.value)}/>
            </div>
            <div>
                <label htmlFor="salary">Salary</label>
                <input type="number" id="salary" value={salary} onChange={(e) => setSalary(e.target.value)}/>
            </div>
            <div>
                <label htmlFor="taxRate">Tax rate %</label>
                <input type="number" id="taxRate" value={taxRate} onChange={(e) => setTaxRate(e.target.value)}/>
            </div>
            <div>
                <button type="button" onClick={onCalculateTax}>Calculate</button>
            </div>
        </>
    )
}

Użytkownik wprowadza dane i wynik jest obliczany przez funkcję: onCalculateTax po kliknięciu w przycisk. Używam useCallback do trzymania funkcji onCalculateTax w pamięci cache. Zauważ, że przez useCallback śledzone są dwie zmienne: salary i taxRate. Za każdym razem, gdy zmieni się wartość, którejś z nich funkcja tworzona jest na nowo. Jeśli zmienimy dane tylko w polu taxpayerName używana jest funkcja z pamięci cache.


Comics: Eat that frog!

Opublikowano: - tagi:
Eat that frog!

Podsumowanie: Luty 2023

Opublikowano: - tagi:

W lutym opublikowałem 8 wpisów:


React:

  1. Jak używać async i await w useEffect?
  2. Typescript i komponenty

Git:

  1. Jak pobrać informacje o zdalnym repozytorium?

JavaScript:

  1. Operator ??
  2. Jak pobrać strefę czasową użytkownika?

TypeScript:

  1. Partial

Narysowałem dwa komiksy:

  1. Big picture
  2. Recursion

Przeczytałem dwie książki:

  1. Historia nowego nazwiska - Elena Ferrante
  2. Mądrość tłumu - Joe Abercrombie

Przesłuchałem trzy audiobooki:

  1. Cień i kość - Leigh Bardugo
  2. Faceci w gumofilcach - Andrzej Pilipiuk
  3. Just Keep Buying - Nick Maggiulli

TypeScript: Partial

Opublikowano: - tagi:

Do czego służy Partial?

Spójrz na poniższy kod:

interface Product {
	name: string;
	price: number;
	description: string;
	weight: number;
}

Mamy tutaj typ Product wszystkie jego pola są wymagane. Więc jeśli spróbujesz stworzyć obiekt o typie Product nie definiując wartości dla wszystkich wymaganych pól TypeScript zgłosi błąd.

Kolejny kod:

const buildProduct = (): Product => {
	return {
		name: randomName(),
		price: randomPrice().
		description: randomDescription(),
		weight: randomWeight()
	}
}

Powyższa funkcja tworzy obiekt typu Product. Przydatny builder, kiedy na przykład piszesz testy. Problem z tym kodem jest taki, gdy potrzebujesz przekazać wartości do konkretnych pól. Oczywiście możesz stworzyć obiekt i przypisać potrzebne wartości.

Można też tak:

const product: Product = buildProduct({ name: 'Super product', price: 150 });

Jak to zrobić?

const buildProduct = (product: Product): Product

Taki zapis oczywiście nie zadziała. W takich sytuacjach sprawdzi się Partial:

const buildProduct = (product: Partial<Product>): Product => {
	return {
		name: randomName(),
		price: randomPrice().
		description: randomDescription(),
		weight: randomWeight(),
		...product
	}
}

Teraz zapis:

const product: Product = buildProduct({ name: 'Super product', price: 150 });

Zadziała.

Partial jak widać pozwala na powiedzenie TypeScript: wartości danego typu są opcjonalne.


JavaScript: Jak pobrać strefę czasową użytkownika?

Opublikowano: - tagi:

Strefa czasowa użytkownika

Piszesz aplikację, której działanie polega na podstawie tego, w jakiej strefie czasowej jest użytkownik? Inny powinien zostać wyświetlony dla użytkownika, który znajduje się w Azji, a inny dla kogoś z Europy?

Skąd mamy wiedzieć, w jakiej strefie czasowej jest użytkownik?

W tym wpisie znajdziesz sposób na pobranie strefy czasowej, w której znajduje się Twój użytkownik. Podanej w systemie IANA. To znaczy:

Europe/Warsaw
Asia/Bangkok

Wiele bibliotek od obsługi czasu korzysta z tego formatu.

Pobranie strefy czasowej użytkownika

Wystarczy wywołać:

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone) // Europe/Warsaw

Metoda resolvedOptions obiekt, który zawiera właściwość timeZone. Wartość jest określona w systemie IANA.