Andreas Richter
Andreas Richter

Reputation: 788

Calling a function on React Element before the Component did mount

I want to use an React Component as a object to make some calculation based on other components before I render / mount them. I have a working solution but I find the part a.type.prototype.calculate.bind(a)() quite dirty.

Here's my current way (also on JSBin):

class ChildComponent extends React.Component {
  calculate() {
    return this.props.a + this.props.b;
  }

  render() {
    return <span>{this.props.a + this.props.b} </span>
  }
}

class ParentComponent extends React.Component {
  render() {
    var children = [
      <ChildComponent a={2} b={3} key="1" />,
      <ChildComponent a={1} b={2} key="2" />
    ];    
    var children_sorted = children.slice();
    
    children_sorted.sort((a,b) => {
      return a.type.prototype.calculate.bind(a)()
      - b.type.prototype.calculate.bind(b)()
    });

    return (
      <h1>Children {children} -> {children_sorted}</h1>      
    );
  }
}

ReactDOM.render(
  <ParentComponent/>,
  document.getElementById('react_example')
);
<div id="react_example"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>

Does somebody have a better way to achieve that?

Upvotes: 1

Views: 1940

Answers (2)

user585886
user585886

Reputation: 23

Is there a reason for using a component for the calculations?

This can be a simple function. This example could probably be simplified further....

class ParentComponent extends React.Component {
  calculate = (a, b) => a + b;

  render() {
    const children = [this.calculate(2, 3), this.calculate(1, 2)];
    const children_sorted = [this.calculate(2, 3), this.calculate(1, 2)].sort();

    return (
      <h1>
        {children.map((x) => x)} => {children_sorted.map((x) => x)}
      </h1>
    );
  }
}

ReactDOM.render(<ParentComponent />, document.getElementById('react_example'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>

<div id="react_example"></div>

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074979

One way that comes to mind is to make calculate static:

static calculate({a, b}) {
  return a + b;
}

...and pass props into it:

children_sorted.sort((a,b) => a.type.calculate(a.props) - b.type.calculate(b.props));

Live Example:

class ChildComponent extends React.Component {
  static calculate({a, b}) {
    return a + b;
  }

  render() {
    return <span>{this.props.a + this.props.b} </span>
  }
}

class ParentComponent extends React.Component {
  render() {
    var children = [
      <ChildComponent a={2} b={3} key="1" />,
      <ChildComponent a={1} b={2} key="2" />
    ];    
    var children_sorted = children.slice();

    children_sorted.sort((a,b) => a.type.calculate(a.props) - b.type.calculate(b.props));

    return (
      <h1>Children {children} -> {children_sorted}</h1>      
    );
  }
}

ReactDOM.render(
  <ParentComponent/>,
  document.getElementById('react_example')
);
<div id="react_example"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>

If the children need to make the same calculation, they can use calculate as well, via ChildComponent.calculate(this.props) (which will always use the version of calculate on ChildComponent or this.constructor.calculate(this.props) which will use the version of calculate on the constructor that created the instance (under normal circumstances). If it's a subclass of ChildComponent and doesn't need its own calculate, it will inherit ChildComponent's (yes, static methods are inherited with class syntax).

Upvotes: 1

Related Questions