我在使用 React 表单和正确管理状态时遇到了麻烦。我在表单(在模式中)中有一个时间输入字段。初始值设置为 中的状态变量getInitialState,并从父组件传入。这本身工作正常。
getInitialState
当我想通过父组件更新默认的start_time值时,问题就出现了。更新本身通过发生在父组件中setState start_time: new_time。然而在我的表单中,默认start_time值永远不会改变,因为它只在中定义一次getInitialState。
setState start_time: new_time
start_time
我曾尝试使用componentWillUpdate来强制改变状态setState start_time: next_props.start_time,这确实有效,但它给出了Uncaught RangeError: Maximum call stack size exceeded错误。
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
componentWillReceiveProps 自 React 16 起被弃用:改用getDerivedStateFromProps
如果我理解正确的话,您有一个父组件,该组件正在将状态传递start_time给ModalBody为其分配自身状态的组件?并且您想从父组件而不是子组件更新该时间。
ModalBody
React 有一些处理这种情况的技巧。(请注意,这是一篇旧文章,现已从网络上删除。以下是有关组件 props 的当前文档的链接)。
使用 props 生成状态getInitialState通常会导致“真实来源”的重复,即真实数据的位置。这是因为getInitialState仅在首次创建组件时才会调用。 只要有可能,就动态计算值以确保它们以后不会不同步并导致维护麻烦。
使用 props 生成状态getInitialState通常会导致“真实来源”的重复,即真实数据的位置。这是因为getInitialState仅在首次创建组件时才会调用。
只要有可能,就动态计算值以确保它们以后不会不同步并导致维护麻烦。
基本上,每当您将父级分配props给子级时state,渲染方法并不总是在 prop 更新时调用。您必须使用该componentWillReceiveProps方法手动调用它。
props
state
componentWillReceiveProps
componentWillReceiveProps(nextProps) { // You don't have to do this check first, but it can help prevent an unneeded render if (nextProps.startTime !== this.state.startTime) { this.setState({ startTime: nextProps.startTime }); } }