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

时间:2015-08-06 07:04:05

标签: javascript reactjs

我在Card中有一些Card component(超过10 Cards component),每张卡片的表格都超过10 textField components。当我输入textFields时,它在textField的类型和更新值之间有延迟。花了两天多的时间后,我发现了我的问题。我认为当我在statein值更新中设置我的值时,它与重新渲染所有Childs(所有Card组件)有关。

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

我的代码如下:

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

我的TextField组件

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

}

我的卡片和卡片组件

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语法,并从代码中删除所有样式标记以简化。

1 个答案:

答案 0 :(得分:2)

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

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

.bind每次都会返回一个新函数,导致每次更新都会呈现Textfield

两种可能的解决方案:

  • 请勿在{{1​​}}内使用.bind.render方法一次在构造函数中,让.bind将标识符传递给Textfield
  • this.props.onValueChange中实施shouldComponentUpdate,如果仅Textfield更改,则返回false