3

I am working on the interface with react. As soon as a button in the 'Buttons' area is clicked, the expression in the 'filter text input' must be used to query a REST interface which returns a list of items as JSON. This data must be passed to the lower left panel to update a tree view. The 'filter text input'+'Buttons' is a controlled input.

+-------------------------------------+
| +-------------------------+-------+ |
| | filter text input       |Buttons| |
| +-------------------------+-------+ |
+----------+--------------------------+
| + item1  | +---------------+        |
| |  +-... | | text input    |        |
| + item2  | +---------------+        |
| |  +-... | +---------------+        |
| + item3  | | text input    |        |
| |  +-... | +---------------+        |
| + item4  |                          |
| |  +-... | ...                      |
+----------|--------------------------+

The canonical approach according to all the tutorials and documentation is to shift the state up to the common parent. However, this is a pretty bad idea because with every single key stroke the whole view will be updated entirely, including the tree in the left panel. Is there a generally accepted way (and good practice) to exchange data between components that belong to the same parent without shifting the state upwards or is there any other approach?

markus barth
  • 63
  • 1
  • 9

3 Answers3

1

I see two options:

  1. Stick with the current approach (which sounds legitimate and straightforward), but utilize shouldComponentUpdate to prevent unnecessary updates.

  2. Use a central data store. Check out Redux.

Or B
  • 1,857
  • 15
  • 22
1

If you have properly put your code together, there should be no performance concern here, and no need to use a centralized data store such as Redux.

However, this is a pretty bad idea because with every single key stroke the whole view will be updated entirely, including the tree in the left panel

Have you tried? If the rest of your tree does not change, React will realise this when traversing the two virtual DOM trees for changes, and will not re-render what has not changed. Unless you are incorrectly using the key prop and forcing a re-render, this will not happen, as the sub-trees are all the same.

It is true, however, that the render method is being called on all of those sub-components. The best way to prevent this, as mentioned by Or B, is to use shouldComponentUpdate; something like the following:

shouldComponentUpdate(nextProps) {
  if (this.props.propA !== nextProps.propA) {
    return true; // re-render
  }
  return false; // don't re-render
}

You can do a full-scale check quite easily using the PureComponent class, like so:

import React, { PureComponent } from 'react';

class MyClass extends PureComponent {
  ...

This does a shallow check of all of the props being passed to the component. The same functionality can be achieved using the pure method of recompose, like so:

import { pure } from 'recompose';

class MyClass extends Component {
  ...
}

export default pure(MyClass); // same thing, really; just a bit more overhead
Lucas
  • 16,930
  • 31
  • 110
  • 182
0

You have to be careful with the way you pass callbacks. If you pass them as arrow functions a different callback is created each time the component is rendered. From the documentation: "However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem." See https://reactjs.org/docs/handling-events.html for more details.

markus barth
  • 63
  • 1
  • 9