Search code examples
reactjseventscomponents

React. How to call method of specific subchild in component tree


I'm starting to learn React and wonder how the following theoretical problem can be solved.

Suppose I have such components.

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        galaxyData:{}
    };
  }

  handleGalaxyCommand(cmd) {
    ...
  }

  render() {
    return (
      <Galaxy galaxyData={this.state.galaxyData} />
    );
  }
}

class Galaxy extends React.Component {
  render() {
    return (this.props.galaxyData.sectors.map((sector) =>
        <Sector sectorData={sector.sectorData} />
    )
    );
  }
}

class Sector extends React.Component {
  render() {
    return (this.props.sectorData.ships.map((ship) =>
        <Ship shipData={ship.shipData} />
    )
    );
  }
}

class Ship extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        x: this.props.shipData.inialX,
        y: this.props.shipData.inialY,
    };
  }

  moveTo(x,y){
  ...
  }

  render() {
    return <div x={this.state.x} y={this.state.y} id={this.props.shipData.id}/>
  }
}

I wrote the code quickly for an example only, so I apologize for any syntax errors. So the component tree looks something like this.

<Galaxy>
    <Sector>
        <Ship/> 
        ...
        <Ship/>
    </Sector>
    <Sector>
        <Ship/> 
        ...
        <Ship/>
    </Sector>
</Galaxy>

There may even be thousands of ships. The ship has a "moveTo" method, which starts the Timer to change the x and y variables in the state, which causes the re-render, the move effect. Let's assume that the Game component receives the command via the "handleGalaxyCommand" method to make the ship start moving.

How to call the "moveTo" method on a ship that interests me?


Solution

  • This is actually possible in react :) in a very simple way.

    But this works only in class-based components (not functional or hooks).

    Basically, you can call any child's methods from the parent if you access it's refs

    Something like:

    class Parent extends Component {
    
        childRef = null;    
    
       componentDidMount() {
           //via ref you can call it
           this.childRef.myCustomMethod();
       }
    
        render() {
            return <Child ref={ref => this.childRef = ref} />
        }
    }
    
    class Child extends Component {
    
        myCustomMethod() {
            console.log("call me ");
        }
    
        render() {
            return <div />;
        }
    

    }

    Check this part of the docs for more details: https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-class-component