Przejdź do treści głównej
Wersja: 0.82

Bezpośrednia manipulacja

Nieoficjalne Tłumaczenie Beta

Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt. Znalazłeś błąd? Zgłoś problem →

Czasami konieczne jest wprowadzanie zmian bezpośrednio w komponencie bez użycia stanu/propsów do wywołania ponownego renderowania całego poddrzewa. Podczas używania Reacta w przeglądarce czasami trzeba bezpośrednio modyfikować węzeł DOM, podobnie jest z widokami w aplikacjach mobilnych. setNativeProps jest w React Native odpowiednikiem bezpośredniego ustawiania właściwości na węźle DOM.

ostrzeżenie

Używaj setNativeProps tylko wtedy, gdy częste ponowne renderowanie tworzy wąskie gardło wydajności!

Bezpośrednia manipulacja nie będzie narzędziem, po które sięgasz często. Zazwyczaj używa się jej tylko do tworzenia płynnych animacji, aby uniknąć narzutu związanego z renderowaniem hierarchii komponentów i uzgadnianiem wielu widoków. setNativeProps działa imperatywnie i przechowuje stan w warstwie natywnej (DOM, UIView itp.), a nie w komponentach Reacta, co utrudnia analizę kodu.

Zanim jej użyjesz, spróbuj rozwiązać problem za pomocą setState i shouldComponentUpdate.

setNativeProps z TouchableOpacity

TouchableOpacity używa wewnętrznie setNativeProps do aktualizacji przezroczystości swojego komponentu potomnego:

tsx
const viewRef = useRef<View>();
const setOpacityTo = useCallback(value => {
// Redacted: animation related code
viewRef.current.setNativeProps({
opacity: value,
});
}, []);

Dzięki temu możemy napisać następujący kod, wiedząc że potomek zaktualizuje swoją przezroczystość w odpowiedzi na dotknięcia, bez konieczności świadomości tego faktu przez komponent potomny ani zmian w jego implementacji:

tsx
<TouchableOpacity onPress={handlePress}>
<View>
<Text>Press me!</Text>
</View>
</TouchableOpacity>

Wyobraźmy sobie, że setNativeProps nie było dostępne. Jednym ze sposobów implementacji przy tym ograniczeniu byłoby przechowywanie wartości przezroczystości w stanie, a następnie aktualizowanie tej wartości przy każdym wywołaniu onPress:

tsx
const [buttonOpacity, setButtonOpacity] = useState(1);
return (
<TouchableOpacity
onPressIn={() => setButtonOpacity(0.5)}
onPressOut={() => setButtonOpacity(1)}>
<View style={{opacity: buttonOpacity}}>
<Text>Press me!</Text>
</View>
</TouchableOpacity>
);

W porównaniu z oryginalnym przykładem jest to kosztowne obliczeniowo - React musi ponownie renderować hierarchię komponentów przy każdej zmianie przezroczystości, nawet jeśli inne właściwości widoku i jego potomków się nie zmieniły. Zwykle ten narzut nie stanowi problemu, ale podczas tworzenia płynnych animacji i obsługi gestów, rozsądna optymalizacja komponentów może poprawić płynność animacji.

Jeśli spojrzysz na implementację setNativeProps w NativeMethodsMixin, zauważysz że jest to opakowanie wokół RCTUIManager.updateView - to dokładnie to samo wywołanie funkcji, które wynika z ponownego renderowania - zobacz receiveComponent w ReactNativeBaseComponent.

Komponenty złożone i setNativeProps

Komponenty złożone nie są obsługiwane przez natywny widok, więc nie możesz wywołać na nich setNativeProps. Rozważ ten przykład:

Po uruchomieniu natychmiast zobaczysz błąd: Touchable child must either be native or forward setNativeProps to a native component. Dzieje się tak dlatego, że MyButton nie jest bezpośrednio obsługiwany przez natywny widok, którego przezroczystość powinna być ustawiona. Możesz to rozumieć w ten sposób: gdybyś zdefiniował komponent za pomocą createReactClass, nie spodziewałbyś się możliwości ustawienia właściwości stylu bez przekazywania jej dalej - chyba że opakowujesz komponent natywny. Podobnie, przekierujemy setNativeProps do komponentu potomnego opartego na natywnym widoku.

Przekazywanie setNativeProps do komponentu potomnego

Ponieważ metoda setNativeProps istnieje dla każdej referencji do komponentu View, wystarczy przekierować referencję w twoim niestandardowym komponencie do jednego z renderowanych komponentów <View />. Oznacza to, że wywołanie setNativeProps na niestandardowym komponencie będzie miało taki sam efekt, jak bezpośrednie wywołanie setNativeProps na opakowywanym komponencie View.

Teraz możesz używać MyButton wewnątrz TouchableOpacity!

Możesz zauważyć, że przekazaliśmy wszystkie propsy do widoku potomnego za pomocą {...props}. Powodem jest fakt, że TouchableOpacity to komponent kompozytowy, który oprócz wymagania setNativeProps na swoim potomku, potrzebuje również by potomek obsługiwał dotyk. W tym celu przekazuje on różne propsy, które wywołują funkcje w komponencie TouchableOpacity. Dla kontrastu, TouchableHighlight jest oparty na natywnym widoku i wymaga jedynie implementacji setNativeProps.

Użycie setNativeProps do edycji wartości TextInput

Innym częstym przypadkiem użycia setNativeProps jest edycja wartości TextInput. Sterowana właściwość (controlled) TextInput czasami może gubić znaki przy niskim bufferDelay i szybkim wprowadzaniu tekstu. Niektórzy deweloperzy preferują pominięcie tej właściwości i bezpośrednią manipulację wartością TextInput za pomocą setNativeProps w razie potrzeby. Przykładowo, poniższy kod demonstruje edycję danych wejściowych po naciśnięciu przycisku:

Metodę clear możesz użyć do wyczyszczenia TextInput, która również wykorzystuje to podejście.

Unikanie konfliktów z funkcją renderującą

Jeśli zaktualizujesz właściwość, która jest również zarządzana przez funkcję renderującą, może to prowadzić do nieprzewidywalnych błędów. Podczas ponownego renderowania komponentu zmiana tej właściwości spowoduje nadpisanie wartości ustawionej przez setNativeProps.

setNativeProps i shouldComponentUpdate

Przez inteligentne stosowanie shouldComponentUpdate możesz uniknąć niepotrzebnego obciążenia podczas rekonsyliacji niezmienionych poddrzew komponentów. W niektórych przypadkach może to wystarczyć, by użyć setState zamiast setNativeProps.

Inne metody natywne

Opisane metody są dostępne w większości domyślnych komponentów React Native. Nie są jednak dostępne w komponentach kompozytowych niebazujących bezpośrednio na natywnym widoku, co dotyczy większości komponentów tworzonych w aplikacji.

measure(callback)

Określa położenie na ekranie, szerokość i wysokość widoku, zwracając wartości asynchronicznie w callbacku. Po powodzeniu callback otrzyma argumenty:

  • x

  • y

  • width

  • height

  • pageX

  • pageY

Pomiary stają się dostępne dopiero po zakończeniu renderowania natywnego. Jeśli potrzebujesz pomiarów natychmiast i nie wymagasz pageX/pageY, rozważ użycie właściwości onLayout.

Zwrócona przez measure() szerokość i wysokość odnoszą się do widoku w viewporcie. Aby uzyskać rzeczywisty rozmiar komponentu, użyj onLayout.

measureInWindow(callback)

Określa położenie widoku w oknie, zwracając wartości asynchronicznie w callbacku. Jeśli główny widok React jest osadzony w innym natywnym widoku, zwraca współrzędne absolutne. Po powodzeniu callback otrzyma:

  • x

  • y

  • width

  • height

measureLayout(relativeToNativeComponentRef, onSuccess, onFail)

Działa jak measure(), ale mierzy widok względem przodka określonego referencją relativeToNativeComponentRef. Oznacza to, że zwracane współrzędne są względem punktu początkowego (x, y) widoku przodka.

uwaga

Tę metodę można również wywołać z procedurą obsługi relativeToNativeNode (zamiast referencji), ale ta wersja jest przestarzała w nowej architekturze.

focus()

Żąda ustawienia fokusa dla danego pola wejściowego lub widoku. Dokładne zachowanie zależy od platformy i typu widoku.

blur()

Usuwa fokus z pola wejściowego lub widoku. Jest to przeciwieństwo działania focus().