У меня проблемы с формой React и правильным управлением состоянием. У меня есть поле ввода времени в форме (в модальном). Начальное значение задается как переменная состояния в getInitialState
и передается из родительского компонента. Это само по себе прекрасно работает.
Проблема возникает, когда я хочу обновить значение start_time по умолчанию через родительский компонент. Само обновление происходит в родительском компоненте через setState start_time: new_time
. Однако в моей форме значение start_time по умолчанию никогда не меняется, поскольку оно определяется только один раз getInitialState
.
Я пытался использовать componentWillUpdate
для принудительного изменения состояния через setState start_time: next_props.start_time
, который на самом деле работал, но дал мне Uncaught RangeError: Maximum call stack size exceeded
ошибки.
Итак, мой вопрос, каков правильный способ обновления состояния в этом случае? Думаю ли я об этом как-то не так?
Текущий код:
@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
Видимо, все меняется .... getDerivedStateFromProps () теперь является предпочтительной функцией.
(приведенный выше код от danburzo @ github)
источник
null
если ничего не изменится, сразу после вашего if, вы должны пойти сreturn null
getDerivedStateFromProps
или напоминание оcomponentWillReceiveProps
не рекомендуется, потому что его использование "часто приводит к ошибкам и несоответствиям".Если что-то меняется извне, рассмотрите возможность полного сброса дочернего компонента с помощью
key
.Предоставление
key
реквизита для дочернего компонента гарантирует, что всякий раз, когда значениеkey
изменяется извне, этот компонент перерисовывается. Например,По его производительности:
источник
JSON.stringify(myObject)
для получения уникального ключа из вашего объекта.Также есть компонент componentDidUpdate .
Функция подписи:
Используйте это как возможность работать на DOM, когда компонент был обновлен. Не вызывается на начальном этапе
render
.Увидимся, вам, вероятно, не нужна производная статья состояния, которая описывает Anti-Pattern для обоих
componentDidUpdate
иgetDerivedStateFromProps
. Я нахожу это очень полезным.источник
componentDidUpdate
потому что это просто и больше подходит для большинства случаев.Новый способ перехвата состоит в том, чтобы использовать useEffect вместо componentWillReceiveProps старым способом:
в функциональном компоненте, управляемом компонентами, становится следующим:
мы устанавливаем состояние с помощью setState, используя useEffect, мы проверяем изменения указанного объекта и предпринимаем действия для обновления состояния при изменении объекта.
источник
Вам, вероятно, не нужно производное состояние
1. Установить ключ от родителя
2. Используйте
getDerivedStateFromProps
/componentWillReceiveProps
При использовании
getDerivedStateFromProps
вы можете сбросить любую часть состояния, но в настоящее время она выглядит немного глючной (v16.7)!, См. Ссылку выше для использования.источник
Из реагирующей документации: https://reactjs.org/blog/2018/06/07/you-probbly-dont-need-derived-state.html
Начиная с версии 16, componentWillReceiveProps устарела. Из реактивной документации, рекомендуемый подход в этом случае является использование
ParentComponent
изModalBody
будет принадлежатьstart_time
государству. Это не мой предпочтительный подход в этом случае, так как я думаю, что модал должен владеть этим состоянием.start_time
государствомModalBody
и использовали его такgetInitialState
же, как вы уже сделали. Чтобы сброситьstart_time
состояние, вы просто измените ключ сParentComponent
источник
Это довольно ясно из их документов:
Используйте: https://reactjs.org/blog/2018/06/07/you-probbly-dont-need-derived-state.html#what-about-memoization
источник
Используйте Memoize
Вывод состояния опом - это прямое манипулирование реквизитом без необходимости истинного вывода. Другими словами, если у вас есть опора, которую можно использовать или трансформировать напрямую, нет необходимости хранить опору в состоянии .
Учитывая, что значение состояния
start_time
является просто опоройstart_time.format("HH:mm")
, информация, содержащаяся в опоре, уже сама по себе достаточна для обновления компонента.Однако, если вы хотите вызывать формат только при смене реквизита, правильный способ сделать это для последней документации - через Memoize: https://reactjs.org/blog/2018/06/07/you-probbly-dont- потребность-наследованный state.html # каких-о-запоминании
источник
Я думаю, что использование ref безопасно для меня, не нужно заботиться о каком-либо методе выше.
источник