【问题标题】:React re-rendering entire map every time one child updates每次一个孩子更新时反应重新渲染整个地图
【发布时间】:2017-03-21 18:09:24
【问题描述】:

改写:

我有一个 FormElements 数组。每次其中一个更改时,我都会将更新发送到父表单。此表单会更新 formData 的状态。

问题是表单中的地图重新渲染了所有的孩子。我需要的是只渲染一个更新的 FormElement。

这会导致性能问题,尤其是对于下拉菜单,它们必须在挂载时从数据库中获取所有可能的值。

代码很多,所以我会尝试在下面放一些相关的东西:

表单页面:

  handleFormElementChange(id, value) {
    var frm = this.state.formData;
    var index=-1;
    for(var i=0;i<frm.length;i++) {
      if(frm[i].id==id) {
        index=i;
        break;
      }
    }
    frm[index].value = value;
    this.setState({formData: frm, selectedElementId: id});
  }

渲染:(这是问题所在,重新渲染所有子节点)

const FormElements = ({formFields}) => (<div> {
  formFields.map(formField => (<FormElement name={formField.name} key={(formField.id != undefined) ? formField.id : "1"} editable={formField.editable} selected={this.state.selectedElementId} value={formField.value} id={formField.id} type={formField.fieldType} handleChange={this.handleFormElementChange.bind(this)}/>)
)} </div>);

FormElement 页面:

componentWillMount() {
    if(this.props.type == this.state.fieldTypesEnum.DROPDOWN) {
       var self = this;
        this.getDropdownVals(this.props.id, function(callback) {
          self.setState({
            dropdownVals: callback
          });
        });
    }
  }

  onChange(e) {
      this.props.handleChange(e.target.id, e.target.value);
  }

渲染:

 if(this.props.type == this.state.fieldTypesEnum.DROPDOWN) {
      var self = this;
      var MakeItem = function(item) {
        return <option key={(item.ID != undefined) ? item.ID : "1"} value={item.ID}>{item.value}</option>;
      };
      let data = this.state.dropdownVals;
      return (<div  class="form-group">
                <label  for={this.props.id}>{this.props.name}:</label>
                <select name={this.props.id} type={this.props.type} maxLength="20" class="form-control" disabled={!this.props.editable} id={this.props.id} value={this.state.isChecked} onChange={this.onChange} ref={(input) => { this.nameInput = input; }}>
                    {data.map(MakeItem)}
                </select>

【问题讨论】:

  • debounce 方法可能适用于此,如果您不希望您的 handleChange 方法如此快速地触发。这是reference
  • 有趣!它仍然不理想,因为每次更改字段时下拉菜单都会闪烁并重新填充
  • 您从数据库中提取数据的方法是根据表单的值还是两者分开?
  • 它使用表单字段 id,如果这是您所要求的

标签: javascript forms reactjs


【解决方案1】:

1) 您可能应该在 componentDidMount 调用您的数据库请求,因为 componentWillMount 还没有访问 dom 的权限。

2) 您可能会使用componentWillUpdate,以便检查您是否从表单中获取有效数据,和/或根据某些情况阻止组件重新呈现。

【讨论】:

    【解决方案2】:

    如果 FormElement 的 key 是不改变的 id,则在 parent 重新加载时不应卸载和重新安装该元素。您确定每次输入字段时都会调用 componentWillMount 方法吗?

    如果每次键入时都重新挂载 FormElement,那么您键入的内容也会消失。

    【讨论】:

    • 公平点。我可能需要发布更多代码,但本质上 Formelement 会更新父 Form 中名为 formData 的状态,然后表单使用它来填充 FormElements 数组
    • 我想我知道为什么重新安装时表单字段的内容没有消失。该值由父级的状态管理,并作为道具传递给子级。因此,您可能希望对所有下拉值执行相同操作。即,将所有下拉值保存在父状态中,就像 formData.id 和 formData.value 一样。然后在子组件的 componentWillMount 方法中,检查从父组件传递的下拉值(例如 formData.dropdownValues)。仅当 formData.dropdownValues 为空或需要更新时才调用 api。
    【解决方案3】:

    FormElements 的数量是动态的吗?如果不是,我建议为父级中的每个 FormElements 设置一个单独的状态。那么你只需要刷新已经改变的元素即可。

    更好的方法是使用 redux-form 来管理 redux store 中的表单状态。每个 FormElement 在 store 中订阅它自己的状态,因此 redux 只刷新需要更改的那个。

    【讨论】:

      猜你喜欢
      • 2016-05-17
      • 2020-08-19
      • 1970-01-01
      • 2017-08-28
      • 2019-06-03
      • 2019-04-22
      • 1970-01-01
      • 1970-01-01
      • 2019-04-18
      相关资源
      最近更新 更多