如何停止在React渲染函数中重新渲染所有的孩子,当我只改变一个孩子的值

How to stop re-rendering all Childs in React render function when I change just one child value?

本文关键字:孩子 改变 一个 何停止 函数 React 新渲染      更新时间:2023-09-26

我在一个Cards component中有一些Card(超过10个Card component),每个卡都有一个超过10个textField components的形式。当我在textFields中输入时,它在textField的类型和更新值之间有延迟。花了2天多后,我找到了问题所在。我认为这是有关重新渲染所有的子(所有的卡组件),当我设置我的值在状态值更新... .

我想知道我错在哪里?如果我的代码是标准的,有没有办法停止重新渲染所有的孩子改变状态后,只是一个textField?

我的代码如下:

MainComponent:

 export default class MainComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value : {}
    };
  }
  static PropTypes = {
    results: PropTypes.array.isRequired
  };
  handleChange(ref, e) {
    this.state.value[ref] = e;
    this.setState(this.state);
  }
  render() {
    const { results } = this.props;
        <Cards>
        { 
        results.map((result, index) => {
            var ref_taxtfield1 = result.id + "taxtfield1";
            var ref_taxtfield2 = result.id + "taxtfield2";
            var ref_taxtfield3 = result.id + "taxtfield3";
            var ref_taxtfield4 = result.id + "taxtfield4";
            var ref_taxtfield5 = result.id + "taxtfield5";
            return <Card key={ result.id } style={ styles.card }>
                <Form>
                    <div style={ styles.innerContainer }>
                        <Textfield
                        name="taxtfield1"
                        label="My Label 1"
                        ref={ref_taxtfield1}
                        onValueChange={this.handleChange.bind(this, ref_taxtfield1)}
                        value={this.state.value[ref_taxtfield1]}
                        />
                        <Textfield
                        name="taxtfield2"
                        label="My Label 2"
                        ref={ref_taxtfield2}
                        onValueChange={this.handleChange.bind(this, ref_taxtfield2)}
                        value={this.state.value[ref_taxtfield2]}
                        />
                        <Textfield
                        name="taxtfield3"
                        label="My Label 3"
                        ref={ref_taxtfield3}
                        onValueChange={this.handleChange.bind(this, ref_taxtfield3)}
                        value={this.state.value[ref_taxtfield3]}
                        />
                        <Textfield
                        name="taxtfield4"
                        label="My Label 4"
                        ref={ref_taxtfield4}
                        onValueChange={this.handleChange.bind(this, ref_taxtfield4)}
                        value={this.state.value[ref_taxtfield4]}
                        />
                        <Textfield
                        name="taxtfield5"
                        label="My Label 5"
                        ref={ref_taxtfield5}
                        onValueChange={this.handleChange.bind(this, ref_taxtfield5)}
                        value={this.state.value[ref_taxtfield5]}
                        />
                    </div>
                </Form>
            </Card>})}
        </Cards>
        }
}

My TextField Component

export default class Textfield extends Input {
  static defaultProps = {
    initialCount: 0,
    value: "",
    defaultValue: "",
    onValueChange: null,
    label: ""
  };
  state = { focused: false };
  onChange = this.onChange.bind(this);
  onChange(e) {
    if(this.props.onValueChange){
      this.props.onValueChange(e.target.value);
    }
  }
  handleOnBlur = this.handleOnBlur.bind(this);
  handleOnBlur(e){
    this.setState({focused: false});
    if(this.props.onBlur){
      this.props.onBlur(e);
    }
  }
  render() {
    const { focused } = this.state;
    const { value, disabled } = this.props;
    return (
      <div>
        <label>{this.props.label}</label>
        <input
          { ...this.inputProps() }
          type="text"
          placeholder={this.props.placeholder}
          defaultValue={this.props.defaultValue}
          onChange={this.onChange}
          onBlur={this.handleOnBlur}
          value={ isCurrency ? formatData.currency(value) : value}
          disabled={disabled}
        />
      </div>
    )
  }
}

My Card and Cards Component

export class Cards extends Component {
    render() {
    const { children, ...props } = this.props;
        return <div {...props} >{ children }</div>;
    }
};
export class Card extends Component {
  render() {
    const { ...props } = this.props;
    return <div {...props} } />
  }
}

我使用ES6语法,并从我的代码中删除所有的样式标签来简化。

您正在传递一个新函数给每个Textfield组件渲染:

onValueChange={this.handleChange.bind(this, ref_taxtfield1)}

.bind每次返回一个新函数,导致每个Textfield在每次更新时渲染。

两种可能的解决方案:

  • 不要在.render中使用.bind.bind在构造函数中调用一次方法,让Textfield传递一个标识符给this.props.onValueChange
  • Textfield中实现shouldComponentUpdate,如果只有this.props.onValueChange改变,则返回false