动态React元素的不必要的DOM更新

时间:2017-04-18 15:24:53

标签: reactjs

我有一个React项目,可以生成一些DOM元素"动态"在JSX中:

<div className='ui form'>
   <h2 className="header">{subtype}</h2>
   {
     subtypes[subtype].fields.map((field) =>
       <div className='field' key={field.name}>
         <label>{field.label}</label>
         <input name={field.name} 
                value={entity[field.name]} 
                onChange={onInputChange}/>
      </div>
      )
   }
</div>

对于特定组件,生成的输入字段在应用程序的生命周期内不会发生变化(只有它们的道具发生变化),因此它只是一种生成实际上是静态的表单的方法。

所以它完全等同于这个&#34;静态&#34; JSX:

<div className='ui form'>
   <h2 className="header">{subtype}</h2>

   <div className='field' key='field1'>
      <label>Field 1</label>
      <input name='field1' 
                value={entity['field1']} 
                onChange={onInputChange}/>
   </div>
   <div className='field' key='field2'>
         <label>Field 2</label>
         <input name='field2' 
                value={entity['field2']} 
                onChange={onInputChange}/>
   </div>
</div>

如果我使用了第一个代码片段,则每次更改状态/道具时都会重新创建HTML DOM元素。如果我使用第二个片段,那么HTML似乎没有改变,只有字段值被更新(React可以在第二个实例中检测到虚拟DOM元素仍然相同,但不是在第一个实例中)

我有没有办法创造&#34;动态&#34;第一个代码示例中的虚拟DOM是否可以缓存和重用,以便React在每个渲染中看到它是相同的?

非常感谢

1 个答案:

答案 0 :(得分:0)

subtypes来自哪里?根据我的理解,你在组件的道具中收到了这个。如果是这种情况,则需要将此变量存储在此组件的状态中。然后,您需要在其componentWillReceiveProps生命周期功能中更新它的状态。

问题是,您的组件只会在调用setState函数时重新呈现。因此,当道具发生变化时(在它已经被安装之后),组件将不会重新渲染。

class SimpleCom extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      subtypes: props.subtypes
    }
  }
  componentWillReceiveProps(props) {
    this.setState({
      subtypes: props.subtypes
    });
  }
  render() {
    const subtypes = this.state.subtypes;
    return (
        <div className='ui form'>
           <h2 className="header">{subtype}</h2>
           {
             subtypes[subtype].fields.map((field) =>
               <div className='field' key={field.name}>
                 <label>{field.label}</label>
                 <input name={field.name} 
                        value={entity[field.name]} 
                        onChange={onInputChange}/>
              </div>
              )
           }
        </div>
    );
  }
}