Mam problem z formularzem React i prawidłowym zarządzaniem stanem. Mam pole wprowadzania czasu w formie (modalnej). Wartość początkowa jest ustawiana jako zmienna stanu w getInitialState
i jest przekazywana z komponentu nadrzędnego. To samo w sobie działa dobrze.
Problem pojawia się, gdy chcę zaktualizować domyślną wartość start_time za pomocą komponentu nadrzędnego. Sama aktualizacja odbywa się w komponencie nadrzędnym za pośrednictwem setState start_time: new_time
. Jednak w mojej formie domyślna wartość parametru czas_początkowy nigdy się nie zmienia, ponieważ jest definiowana tylko raz getInitialState
.
Próbowałem użyć componentWillUpdate
do wymuszenia zmiany stanu setState start_time: next_props.start_time
, która faktycznie działała, ale dała mi Uncaught RangeError: Maximum call stack size exceeded
błędy.
Więc moje pytanie brzmi: jaki jest właściwy sposób aktualizacji stanu w tym przypadku? Czy myślę o tym jakoś źle?
Aktualny kod:
@ModalBody = React.createClass
getInitialState: ->
start_time: @props.start_time.format("HH:mm")
#works but takes long and causes:
#"Uncaught RangeError: Maximum call stack size exceeded"
componentWillUpdate: (next_props, next_state) ->
@setState(start_time: next_props.start_time.format("HH:mm"))
fieldChanged: (fieldName, event) ->
stateUpdate = {}
stateUpdate[fieldName] = event.target.value
@setState(stateUpdate)
render: ->
React.DOM.div
className: "modal-body"
React.DOM.form null,
React.createElement FormLabelInputField,
type: "time"
id: "start_time"
label_name: "Start Time"
value: @state.start_time
onChange: @fieldChanged.bind(null, "start_time”)
@FormLabelInputField = React.createClass
render: ->
React.DOM.div
className: "form-group"
React.DOM.label
htmlFor: @props.id
@props.label_name + ": "
React.DOM.input
className: "form-control"
type: @props.type
id: @props.id
value: @props.value
onChange: @props.onChange
[..]going to be deprecated in the future
Najwyraźniej rzeczy się zmieniają .... getDerivedStateFromProps () jest teraz preferowaną funkcją.
(powyższy kod autorstwa danburzo @ github)
źródło
null
jeśli nic nie powinno się zmienić, więc zaraz po tym, jeśli, powinieneś iśćreturn null
getDerivedStateFromProps
dogłębnie omawiacomponentWillReceiveProps
jest przestarzałe, ponieważ używanie go „często prowadzi do błędów i niespójności”.Jeśli coś zmienia się z zewnątrz, rozważ całkowite zresetowanie komponentu potomnego
key
.Dostarczenie
key
rekwizytu do komponentu potomnego zapewnia, że ilekroć wartośćkey
zmian z zewnątrz, ten komponent jest renderowany ponownie. Na przykład,Na temat jego wydajności:
źródło
JSON.stringify(myObject)
aby uzyskać unikalny klucz ze swojego obiektu.Dostępna jest również funkcja componentDidUpdate .
Sygnatura funkcji:
Wykorzystaj to jako okazję do pracy na DOM, gdy komponent zostanie zaktualizowany. Nie jest wywoływany na początku
render
.Do zobaczenia prawdopodobnie nie potrzebujesz artykułu o stanie pochodnym , który opisuje Anti-Pattern zarówno dla, jak
componentDidUpdate
i dlagetDerivedStateFromProps
. Uważam to za bardzo przydatne.źródło
componentDidUpdate
ponieważ jest prosty i bardziej odpowiedni dla większości przypadków.Nowym sposobem przechwytywania tego jest użycie useEffect zamiast componentWillReceiveProps w stary sposób:
staje się następujący w funkcjonalnym elemencie napędzanym hakami:
ustawiamy stan za pomocą setState, za pomocą useEffect sprawdzamy zmiany w określonym rekwidziecie i podejmujemy akcję, aby zaktualizować stan po zmianie rekwizytu.
źródło
Prawdopodobnie nie potrzebujesz stanu pochodnego
1. Ustaw klucz od rodzica
2. Użyj
getDerivedStateFromProps
/componentWillReceiveProps
Za pomocą
getDerivedStateFromProps
możesz zresetować dowolną część stanu, ale w tej chwili wydaje się to trochę wadliwe (v16.7) !, patrz powyższy link do użyciaźródło
Z dokumentacji reagowania: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
Od React 16 składnik componentWillReceiveProps jest przestarzały. Z dokumentacji reagowania zalecane jest w tym przypadku podejście
ParentComponent
zModalBody
będzie właścicielemstart_time
stanu. To nie jest moje preferowane podejście w tym przypadku, ponieważ uważam, że modal powinien posiadać ten stan.start_time
stanuModalBody
i będziesz używać gogetInitialState
tak, jak już to zrobiłeś. Aby zresetowaćstart_time
stan, wystarczy zmienić klucz zParentComponent
źródło
Wyraźnie wynika to z ich dokumentów:
Użyj: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
źródło
Użyj Memoize
Wyprowadzenie stanu przez operację jest bezpośrednią manipulacją rekwizytami, bez potrzeby prawdziwego wyprowadzania. Innymi słowy, jeśli masz rekwizyt, który można wykorzystać lub przekształcić bezpośrednio, nie ma potrzeby przechowywania rekwizytu w stanie .
Biorąc pod uwagę, że wartością stanu
start_time
jest po prostu rekwizytstart_time.format("HH:mm")
, informacje zawarte w rekwizytach są już same w sobie wystarczające do aktualizacji komponentu.Jeśli jednak chcesz wywoływać format tylko w przypadku zmiany rekwizytów, poprawnym sposobem wykonania tego w najnowszej dokumentacji byłoby użycie funkcji Zapamiętaj: https://reactjs.org/blog/2018/06/07/you-probably-dont- need-pochodzą-stan.html # what-about-memoization
źródło
Myślę, że użycie ref jest dla mnie bezpieczne, nie potrzebuję dbać o jakąś metodę powyżej.
źródło