Mam zewnętrzny (do komponentu), obserwowalny obiekt, na którym chcę nasłuchiwać zmian. Gdy obiekt jest aktualizowany, emituje zdarzenia zmiany, a następnie chcę ponownie wysłać komponent po wykryciu jakiejkolwiek zmiany.
W przypadku najwyższego poziomu React.render
było to możliwe, ale w komponencie nie działa (co ma sens, ponieważ render
metoda zwraca obiekt).
Oto przykład kodu:
export default class MyComponent extends React.Component {
handleButtonClick() {
this.render();
}
render() {
return (
<div>
{Math.random()}
<button onClick={this.handleButtonClick.bind(this)}>
Click me
</button>
</div>
)
}
}
Kliknięcie przycisku wywołuje wewnętrznie this.render()
, ale to nie jest to, co faktycznie powoduje renderowanie (możesz to zobaczyć w działaniu, ponieważ tekst utworzony przez {Math.random()}
nie zmienia się). Jednakże, jeśli po prostu zadzwonić this.setState()
zamiast this.render()
, to działa dobrze.
Tak więc myślę, że moje pytanie brzmi: czy komponenty React muszą mieć stan, aby móc ponownie wysłać? Czy istnieje sposób zmuszenia komponentu do aktualizacji na żądanie bez zmiany stanu?
this.forceUpdate()
jest dobrym rozwiązaniem, natomiast reszta wszystkich odpowiedzi i kilka uwag są przed stosowaniemforceUpdate()
. Czy w takim razie można powiedzieć, że pytanie nie uzyskało jeszcze właściwego rozwiązania / odpowiedzi?Odpowiedzi:
W swoim komponencie możesz zadzwonić w
this.forceUpdate()
celu wymuszenia ponownego wydania.Dokumentacja: https://facebook.github.io/react/docs/component-api.html
źródło
this.forceUpdate()
nie jest to bardzo dobre rozwiązanie problemu pytających, jest to prawidłowa odpowiedź na pytanie postawione w tytule. Chociaż ogólnie należy tego unikać, istnieją sytuacje, w których forceUpdate jest dobrym rozwiązaniem.shouldComponentUpdate()
swoje rozwiązanie bezużytecznym.forceUpdate
należy tego unikać, ponieważ odbiega on od sposobu myślenia React. Dokumenty React przytaczają przykład, kiedyforceUpdate
można go użyć:Chciałbym jednak zaproponować pomysł, że nawet przy głęboko zagnieżdżonych obiektach nie
forceUpdate
jest potrzebny. Dzięki zastosowaniu niezmiennego źródła danych zmiany stają się tanie; zmiana zawsze spowoduje powstanie nowego obiektu, dlatego musimy tylko sprawdzić, czy zmieniło się odwołanie do obiektu. Możesz użyć biblioteki Immutable JS, aby zaimplementować niezmienne obiekty danych w swojej aplikacji.Zmiana klucza elementu, który chcesz ponownie renderować, zadziała. Ustaw rekwizyt klucza na elemencie poprzez stan, a następnie, gdy chcesz zaktualizować ustaw stan, aby mieć nowy klucz.
Następnie następuje zmiana i resetujesz klucz
Chcę zauważyć, że zastąpi to element, który zmienia klucz. Przykładem tego może być pole wprowadzania pliku, które chcesz zresetować po przesłaniu obrazu.
Chociaż prawdziwa odpowiedź na pytanie PO byłaby taka
forceUpdate()
, znalazłem to rozwiązanie pomocne w różnych sytuacjach. Chcę również zauważyć, że jeśli używasz,forceUpdate
możesz przejrzeć kod i sprawdzić, czy jest inny sposób na zrobienie tego.UWAGA 1-9-2019:
Powyższe (zmiana klucza) całkowicie zastąpi element. Jeśli znajdziesz klucz do wprowadzenia zmian, prawdopodobnie masz problem z innym kodem. Użycie
Math.random()
klucza spowoduje ponowne utworzenie elementu przy każdym renderowaniu. NIE zalecałbym aktualizacji klucza w ten sposób, ponieważ zareaguj używa klucza do określenia najlepszego sposobu ponownego renderowania.źródło
key
. Po pierwsze, jego zamiar jest niejasny. Czytelnik twojego kodu będzie musiał ciężko pracować, aby zrozumieć, dlaczego używasz wkey
ten sposób. Po drugie, nie jest to bardziej czyste niżforceUpdate
. Reakcja „czysta” oznacza, że wizualna prezentacja twojego komponentu jest w 100% zależna od jego stanu, więc jeśli zmienisz dowolny stan, zostanie zaktualizowany. Jeśli jednak masz jakieś głęboko zagnieżdżone obiekty (scenariuszforceUpdate
dokumentuje powód, aby z nich skorzystać), to użycieforceUpdate
wyjaśnia. Po trzecie,Math.random()
jest… losowy. Teoretycznie mógłby wygenerować tę samą liczbę losową.forceUpdate
jest sposobem React na zrobienie tego.W rzeczywistości
forceUpdate()
jest to jedyne prawidłowe rozwiązanie, któresetState()
może nie wyzwalać ponownego renderowania, jeśli zaimplementowana zostanie dodatkowa logikashouldComponentUpdate()
lub gdy po prostu wrócifalse
.wymusić aktualizację()
setState ()
forceUpdate()
może zostać wywołany z twojego komponentu przezthis.forceUpdate()
Haki: Jak zmusić komponent do ponownego renderowania za pomocą haków w React?
BTW: Czy mutujesz stan, czy zagnieżdżone właściwości nie propagują się?
źródło
this.state
poza konstruktorem powinno również generować błąd. Być może nie uczynił tego w 2016 r .; ale jestem pewien, że teraz to robi.Unikałem
forceUpdate
, wykonując następujące czynnościwięc dzięki takiemu ulepszeniu kodu twój komponent będzie UNIKALNY i będzie renderowany w naturalny sposób
źródło
this.state.rows.map((item) => <MyComponent item={item} key={item.id} /> )
Jeśli chcesz, aby komunikowały się dwa komponenty React, które nie są powiązane relacją (rodzic-dziecko), wskazane jest użycie Flux lub podobnych architektur.
To, co chcesz zrobić, to nasłuchiwać zmian w
obserwowalnym składniku komponentów, który przechowuje model i jego interfejs, i zapisywać dane, które powodują zmianę renderowania jakstate
wMyComponent
. Gdy sklep wypycha nowe dane, zmieniasz stan swojego komponentu, co automatycznie uruchamia renderowanie.Zwykle powinieneś unikać używania
forceUpdate()
. Z dokumentacji:źródło
react-redux
aby automatycznie mapować stan sklepu na rekwizyty komponentowe w razie potrzeby na podstawie dostarczonej funkcji mapowania.forceUpdate
użyj haków lub wybierz HOC
Korzystając z haków lub wzorca HOC (komponentu wyższego rzędu) , możesz mieć automatyczne aktualizacje po zmianie sklepów. Jest to bardzo lekkie podejście bez ram.
useStore Hooks sposób obsługi aktualizacji sklepu
withStores HOC obsługuje aktualizacje sklepu
Klasa SimpleStore
Jak używać
W przypadku haków:
W przypadku HOC:
UPEWNIJ SIĘ, że możesz eksportować swoje sklepy jako singleton, aby skorzystać z globalnej zmiany:
To podejście jest dość proste i działa dla mnie. Pracuję również w dużych zespołach, używam Redux i MobX i uważam, że są one również dobre, ale po prostu dużo bojlera. Po prostu osobiście podoba mi się moje własne podejście, ponieważ zawsze nienawidziłem dużo kodu za coś, co może być proste, kiedy jest to potrzebne.
źródło
this._data = {...this._data, ...newData}
.Inne odpowiedzi próbowały zilustrować, jak możesz, ale chodzi o to, że nie powinieneś . Nawet hacke rozwiązanie zmiany klucza nie ma sensu. Potęgą React jest rezygnacja z ręcznego zarządzania czasem, gdy coś powinno się renderować, a zamiast tego skupienie się na tym, jak coś powinno być mapowane na danych wejściowych. Następnie dostarcz strumień wejściowy.
Jeśli musisz ręcznie wymusić ponowne renderowanie, prawie na pewno nie robisz czegoś dobrze.
źródło
Możesz to zrobić na kilka sposobów:
1. Użyj
forceUpdate()
metody:Podczas korzystania z tej
forceUpdate()
metody mogą wystąpić pewne usterki . Jednym z przykładów jest to, że ignorujeshouldComponentUpdate()
metodę i ponownie renderuje widok bez względu na to, czyshouldComponentUpdate()
zwraca false. Z tego powodu należy w miarę możliwości unikać stosowania forceUpdate ().2. Przekazanie this.state do
setState()
metodyPoniższy wiersz kodu rozwiązuje problem z poprzednim przykładem:
Naprawdę wszystko, co to robi, to zastąpienie bieżącego stanu bieżącym stanem, który uruchamia ponowne renderowanie. To wciąż niekoniecznie najlepszy sposób na robienie rzeczy, ale eliminuje niektóre usterki, które możesz napotkać za pomocą metody forceUpdate ().
źródło
this.setState(prevState => prevState);
Istnieje kilka sposobów ponownego wysłania komponentu:
Najprostszym rozwiązaniem jest użycie metody forceUpdate ():
Jeszcze jednym rozwiązaniem jest utworzenie nieużywanego klucza w stanie (nonUsedKey) i wywołanie funkcji setState z aktualizacją tego nonUsedKey:
Lub przepisz cały aktualny stan:
Zmiana rekwizytów zapewnia również ponowne wysyłanie komponentów.
źródło
Dla kompletności możesz to również osiągnąć w elementach funkcjonalnych:
Lub jako hak wielokrotnego użytku:
Zobacz: https://stackoverflow.com/a/53215514/2692307
Należy pamiętać, że stosowanie mechanizmu aktualizacji siły jest nadal złą praktyką, ponieważ jest sprzeczne z mentalnością reagowania, dlatego należy go w miarę możliwości unikać.
źródło
Możemy użyć this.forceUpdate () jak poniżej.
Część Element „Math.random” w DOM jest aktualizowana tylko wtedy, gdy używasz setState do ponownego renderowania komponentu.
Wszystkie odpowiedzi tutaj są poprawne i stanowią uzupełnienie pytania dla zrozumienia. Wiemy, że ponowne renderowanie komponentu bez użycia setState ({}) odbywa się za pomocą forceUpdate ().
Powyższy kod działa z setState jak poniżej.
źródło
Kolejna odpowiedź na kopię zaakceptowanej odpowiedzi :-)
React odradza korzystanie z
forceUpdate()
ponieważ generalnie mają bardzo „to jest jedyny sposób na to” podejście do programowania funkcjonalnego. W wielu przypadkach jest to w porządku, ale wielu programistów React ma tło OO, a przy takim podejściu słuchanie obserwowalnego obiektu jest całkowicie w porządku.A jeśli to zrobisz, prawdopodobnie wiesz, że MUSISZ ponownie renderować, gdy możliwe do zaobserwowania „pożary”, i dlatego powinieneś użyć,
forceUpdate()
a tak naprawdę to plusshouldComponentUpdate()
NIE jest tutaj zaangażowany.Narzędzia takie jak MobX, które przyjmują podejście OO, faktycznie robią to pod powierzchnią (faktycznie wywołania MobX
render()
bezpośrednio)źródło
Uważam, że najlepiej jest unikać forceUpdate (). Jednym ze sposobów wymuszenia ponownego renderowania jest dodanie zależności render () od tymczasowej zmiennej zewnętrznej i zmiana wartości tej zmiennej w razie potrzeby.
Oto przykład kodu:
Wywołaj this.forceChange (), gdy musisz wymusić ponowne renderowanie.
źródło
ES6 - podaję przykład, który był dla mnie pomocny:
W „krótkiej instrukcji if” możesz przekazać pustą funkcję w następujący sposób:
To wydaje się być najkrótszym podejściem.
źródło
forceUpdate();
metoda będzie działać, ale zaleca się jej użyciesetState();
źródło
Aby osiągnąć to, co opisujesz, spróbuj this.forceUpdate ().
źródło
Innym sposobem jest wywołanie
setState
, I zachować stan:this.setState(prevState=>({...prevState}));
źródło
forceUpdate (), ale za każdym razem, gdy słyszę, że ktoś o tym mówi, jest śledzone, że nigdy nie powinieneś tego używać.
źródło
Możesz użyć forceUpdate (), aby sprawdzić więcej szczegółów ( forceUpdate () ).
źródło