byake
byake

Reputation: 331

How to pass callback from one child component to another

I have a main component, App, which has two child components, Player, and VideoList, where Player is a wrapper around react-player, heavily based off of the react-player demo.

Player has a method renderLoadButton() which creates a button that loads a particular video when clicked. I would like to have several of these buttons inside of my VideoList component.

I am attempting to pass the renderLoadButton() function up into the parent component, and then down into the VideoList component where I can call it.

Here is the code for render() function of the parent component. Both my <Player/> and <VideoList/> components instantiated here.

I get the following error on the line mentioned in the comment.

TypeError: Cannot read property 'renderLoadButton' of undefined

render() {
    const dragHandlers = {onStart: this.onStart, onStop: this.onStop};
    const {deltaPosition, controlledPosition} = this.state;

    return (
      <div className="App">
          <div className="fullscreen">

              <Draggable handle="strong" bounds={'body'}{...dragHandlers}>
                  <div style={{position: 'absolute', bottom: '30%', right: '50%'}} className="video-box no-cursor">
                      <Player ref={instance=>{this.player = instance}} title="VIDEO" url='https://streamable.com/nfec3'/>
                  </div>
              </Draggable>
              <Draggable handle="strong" bounds={'body'}{...dragHandlers}>

               <div>
                   {/*Error on the following line*/}
                   <VideoList callback = {(x,y)=> this.player.renderLoadButton(x,y)}/>
               </div>
              </Draggable>
          </div>

          <div className="App-footer">
              <img src={vinyl} className="App-logo" alt="logo" />
              <h1>Radio</h1>
          </div>
      </div>
    );
}

Upvotes: 0

Views: 2078

Answers (1)

aravind_reddy
aravind_reddy

Reputation: 5466

As per the code you provided you are doing it right i have created similar working model as yours it is working fine: https://codesandbox.io/s/6y5p9woqq3

You can add your code to sandbox so that we will able to figure out what is the problem.

Edit

The Problem with your code is not index.js but is in VideoList.js as per your minimal code VideoList.js:

    import React, { Component } from "react";

class VideoList extends Component {
  render() {
    console.log("dd");
    return this.props.callback('www.something.com','BUTTON');
  }
}
export default VideoList;

Here you are trying to return a prop which contains a function not the original jsx for better clarity try console logging like this console.log("dd",this.props.callback) which shows a object returning your this.player.renderLoadButton function. so when you are trying to return it which returns just a function which cannot be rendered it is causing errors.

So if you have to pass that function which returns jsx don't use ref.Create a new obj or instance of Player class and extract the function from it and then pass it as prop to the videoList and the call it in render return.

so your App component should look like:

    class App extends Component {
  render() {
    const obj = new Player 
    const func = obj.renderLoadButton   
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <Player title="VIDEO" url='https://streamable.com/nfec3'/>
        <VideoList func={func} />
      </div>
    );
  }
}

then your VideoList looks like:

    class VideoList extends Component {
  render() {
    console.log("dd");
    return (
   <div>
     { this.props.func('www.something.com','BUTTON') }
    </div>
    )
  }
}
export default VideoList;

here is working code :https://codesandbox.io/s/jpqnxwyyy

Edit 2:

i don't think it is possible that way. one thing you can do is use the same jsx every where and use the another function as props every where to call again. like this: https://codesandbox.io/s/7zwyl0yp3j

Upvotes: 1

Related Questions