在 React 表单中更新道具更改状态 [英] Updating state on props change in React Form

查看:65
本文介绍了在 React 表单中更新道具更改状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 React 表单和正确管理状态时遇到问题.我有一个表单中的时间输入字段(在模态中).初始值在 getInitialState 中设置为状态变量,并从父组件传入.这本身工作正常.

当我想通过父组件更新默认的 start_time 值时,问题就出现了.更新本身通过 setState start_time: new_time 在父组件中发生.但是在我的表单中,默认的 start_time 值永远不会改变,因为它只在 getInitialState 中定义了一次.

我尝试使用 componentWillUpdate 通过 setState start_time: next_props.start_time 强制改变状态,这确实有效,但给了我 Uncaught RangeError: 超出最大调用堆栈大小 错误.

所以我的问题是,在这种情况下更新状态的正确方法是什么?我是不是在想这个错误?

当前代码:

@ModalBody = React.createClassgetInitialState: ->开始时间:@props.start_time.format("HH:mm")#有效但需要很长时间并导致:#未捕获的范围错误:超出最大调用堆栈大小"componentWillUpdate: (next_props, next_state) ->@setState(start_time: next_props.start_time.format("HH:mm"))fieldChanged: (fieldName, event) ->状态更新 = {}stateUpdate[fieldName] = event.target.value@setState(stateUpdate)渲染:->React.DOM.div类名:模态体"React.DOM.form 空,React.createElement FormLabelInputField,类型:时间"id:开始时间"label_name: "开始时间"值:@state.start_timeonChange: @fieldChanged.bind(null, "start_time")@FormLabelInputField = React.createClass渲染:->React.DOM.div班级名称:表单组"响应.DOM.labelhtmlFor:@props.id@props.label_name + ":"响应.DOM.input类名:表单控件"类型:@props.typeid:@props.id值:@props.valueonChange:@props.onChange

解决方案

<块引用>

componentWillReceiveProps 自 react 16 起被弃用:改用 getDerivedStateFromProps>

如果我理解正确,您有一个父组件将 start_time 传递给 ModalBody 组件,该组件将其分配给自己的状态?并且您想从父组件而不是子组件更新该时间.

React 有一些处理这种情况的技巧.(注意,这是一篇旧文章,此后已从网上删除.这是当前 关于组件道具的文档).

<块引用>

getInitialState 中使用 props 生成状态通常会导致真实数据来源"的重复,即真实数据在哪里.这是因为 getInitialState 仅在首次创建组件时调用.

只要有可能,即时计算值以确保它们不会在以后失去同步并导致维护问题.

基本上,每当您将父级的 props 分配给子级的 state 时,并不总是在 prop 更新时调用 render 方法.您必须使用 componentWillReceiveProps 方法手动调用它.

componentWillReceiveProps(nextProps) {//你不必先做这个检查,但它可以帮助防止不必要的渲染if (nextProps.startTime !== this.state.startTime) {this.setState({ startTime: nextProps.startTime });}}

I am having trouble with a React form and managing the state properly. I have a time input field in a form (in a modal). The initial value is set as a state variable in getInitialState, and is passed in from a parent component. This in itself works fine.

The problem comes when I want to update the default start_time value through the parent component. The update itself happens in the parent component through setState start_time: new_time. However in my form, the default start_time value never changes, since it is only defined once in getInitialState.

I have tried to use componentWillUpdate to force a change in state through setState start_time: next_props.start_time, which did actually work, but gave me Uncaught RangeError: Maximum call stack size exceeded errors.

So my question is, what's the correct way of updating state in this case? Am I thinking about this wrong somehow?

Current Code:

@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 is depcricated since react 16: use getDerivedStateFromProps instead

If I understand correctly, you have a parent component that is passing start_time down to the ModalBody component which assigns it to its own state? And you want to update that time from the parent, not a child component.

React has some tips on dealing with this scenario. (Note, this is an old article that has since been removed from the web. Here's a link to the current doc on component props).

Using props to generate state in getInitialState often leads to duplication of "source of truth", i.e. where the real data is. This is because getInitialState is only invoked when the component is first created.

Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.

Basically, whenever you assign parent's props to a child's state the render method isn't always called on prop update. You have to invoke it manually, using the componentWillReceiveProps method.

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 });
  }
}

这篇关于在 React 表单中更新道具更改状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆