echo_zero echo_zero - 1 month ago 19
React JSX Question

ReactJS: Parent child partial update

I'm having a bit of a trouble getting my head around how i would communicate between my parent and child components in my specific use case.

I have a child component that renders some points using an external lib.

What I'm currently doing is implementing componentDidMount/Update and use the external lib to render the points in this.props.points (which is an array provided by the parent component).

Rendering the points involves looping through them and call something like ExternalLib.addPoint(point).

What i would like to do, instead of looping through all the points everytime this.props.points changes, is making the parent component add (or remove) individual points to the child component.

Is it React friendly to call something like this.refs.myChild.addPoint(point) in the parent component?

Are there other techniques to achieve something like this?

Update

Here's some code (https://jsfiddle.net/69z2wepo/61366/):

const ExternalLib = {

addPoint: function(el, point) {
var li = document.createElement("li");
li.innerHTML = point;
el.appendChild(li);
}
}

class Child extends React.Component {

componentDidMount() {
this.renderPoints();
}

componentDidUpdate() {
this.renderPoints();
}

renderPoints() {
const el = this.refs.points;
el.innerHTML = '';
this.props.points.forEach(function(point) {
ExternalLib.addPoint(el, point);
});
}

render() {
console.log('render')
return (
<div>
<ul ref="points"></ul>
</div>
);
}
}

class Parent extends React.Component {

constructor() {

super();

this.state = {
points: []
};
}

addPoint() {

const points = this.state.points.slice();

points.push((new Date()).getTime());

this.setState({
points: points
});
}

render() {
return (
<div>
<button onClick={this.addPoint.bind(this)}>Add Point</button>
<Child points={this.state.points} />
</div>
);
}
}

ReactDOM.render(
<Parent />,
document.getElementById('container')
);


This is simplified because in this example I could generate the markup directly making use of map and leveraging React's partial DOM update - the external lib does some extra stuff that's not in this question's scope.

Thanks!

Answer

If you want to interfere with React rendering process, you can code shouldcomponentupdate.

In your children, if you make shouldcomponentupdate return false and call ExternalLib.addPoint(point), it should do the job:

shouldComponentUpdate(nextProps){
  //comparePoints() is a function able to find if a new point is present in the list, comparing existing used points with new one
  var newPoint = comparePoints(this.props.points, nextProps.points)

  if(newPoint){
    ExternalLib.addPoint(newPoint);
    //forbide re-render
    return false;
  }

  //enable other update
  return true;
}