P
P
Pogran2016-09-16 11:48:50
React
Pogran, 2016-09-16 11:48:50

How does render happen?

I can't figure out why my components keep getting render()
. I have a component Tree .

class Tree extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      oldValue: '',
      newValue: '',
      oldKey: '',
      newKey: '',
      level: '',
      action: false,
    };

    this.onAddLevel = this.onAddLevel.bind(this);
  }

  resetState() {
    this.setState({
      action: false,
      newKey: '',
      newValue: '',
      oldKey: '',
      oldValue: ''
    });
  }


  onAddLevel(e) {
    e.preventDefault();

    this.setState({
      level: e.target.dataset.level,
      oldKey: e.target.dataset.key,
      action: 'add-level',
      newValue: '',
      newKey: ''
    });
  }

  render() {
    console.log('Tree');

    return (
      <div className="tree">
        <TreeStructure
          addLevel={this.onAddLevel}
          structure={this.props.entity.structure}
        />
      </div>
    );
  }
}

Tree.propTypes = {
  entity: React.PropTypes.object.isRequired,
  addLevel: React.PropTypes.func.isRequired
};

export default Tree;

And the TreeStructure component.
import React from 'react';
import ControlLink from './ControlLink';
import isEmpty from 'lodash/isEmpty';

class TreeStructure extends React.Component {
  constructor(props) {
    super(props);
  }

  renderTree(object, level ='', padding = 0) {
    console.log('render Tree');
    padding  += 12;

    return (
      Object.keys(object).map(key => {
        if(typeof object[key] == 'string') {
          return (
            this.renderChildString(key, object[key], level ,padding)
          )
        } else {
          return (
            this.renderLevelString(key, object[key], level, padding)
          );
        }
      })
    );
  }

  renderChildString(key, value, level='',padding) {
    return (
      <div className="row-tree" style={{paddingLeft: `${padding}px`}} key={key} >
        <b>{key}</b>: {value}

        <div className="pull-right">
          <ControlLink
            title="Add level"
            level={level}
            keyVal={key}
            className="create-element"
            parentClassName="fa fa-plus"
            onClick={this.props.addLevel}
          />

        </div>
        <div>
          {this.renderTree(object, levelKey, padding)}
        </div>
        <div style={{paddingLeft: `${padding}px`}} className="row-tree">
          <div>&#125;</div>
        </div>
      </div>
    );
  }

  render() {
    console.log('render structure');

    return (
      <div>
        {this.renderTree(this.props.structure)}
      </div>
    );
  }
}

TreeStructure.propTypes = {
  structure: React.PropTypes.object.isRequired,
  addLevel: React.PropTypes.func.isRequired
};

export default TreeStructure;

So I click on the button in the TreeStructure and the addLevel of the parent is called. The question is why then all renders are called in a chain, including TreeStructure. That is, the point here is that when you click, only the state of the Tree changes, while nothing changes for the TreeStructure. So why is render being called on TreeStructure . And how can I make it so that when clicked, the render of the TreeStructure is not called

Answer the question

In order to leave comments, you need to log in

1 answer(s)
U
UsulPro, 2016-11-25
@Pogran

Because starting Render on the parent starts Render on all child components. This is the essence of React.
You can manually control whether the component will be rendered if you add to it (in your case in the TreeStructure) the shouldComponentUpdate(nextProps, nextState)
function. If it returns false, then the component will not be rendered.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question