如何将回调从一个子组件传递到另一个子组件

时间:2018-06-19 04:47:45

标签: javascript reactjs

我有一个主要组件App,它有两个子组件PlayerVideoList,其中Playerreact-player的包装,严重基于react-player演示。

Player有一个方法renderLoadButton(),可以创建一个按钮,在点击时加载特定视频。我想在我的VideoList组件中有几个这样的按钮。

我正在尝试将renderLoadButton()函数传递到父组件,然后向下传递到我可以调用它的VideoList组件。

以下是父组件的render()函数的代码。我的<Player/><VideoList/>组件都在这里实例化了。

我在评论中提到的行上收到以下错误。

  

TypeError:无法读取未定义

的属性'renderLoadButton'
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>
    );
}

2 个答案:

答案 0 :(得分:1)

根据您提供的代码,您正在做正确的我已经创建了与您相似的工作模型它正常工作:   https://codesandbox.io/s/6y5p9woqq3

您可以将代码添加到沙箱中,以便我们能够找出问题所在。

修改

您的代码问题不是index.js,而是根据您的最小代码在VideoList.js 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;

在这里,您尝试返回一个包含函数而不是原始jsx的道具,以便更清晰地尝试控制台日志记录   console.log("dd",this.props.callback) 它显示了一个返回this.player.renderLoadButton函数的对象。因此,当您尝试返回它时,它只返回一个无法渲染的函数,这会导致错误。

因此,如果你必须传递返回jsx的函数,请不要使用ref.Create一个新的obj或Player类的实例,并从中提取函数,然后将其作为prop传递给videoList,并将其调用为render返回。

因此您的App组件应如下所示:

    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>
    );
  }
}

然后你的VideoList看起来像:

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

这是工作代码:https://codesandbox.io/s/jpqnxwyyy

编辑2:

我不认为这样可能。你可以做的一件事是在每个地方使用相同的jsx,并使用另一个函数作为道具,每个地方再次调用。像这样:https://codesandbox.io/s/7zwyl0yp3j

答案 1 :(得分:0)

使用this.METHOD_NAME时,您必须使用初始方法!

constructor(props){
  super(props);
  this.renderLoadButton = this.renderLoadButton.bind(this);
}

renderLoadButton(x,y){
  console.log(x,y); // for example
}

render(){
  return(
    ...
      <VideoList callback={this.renderLoadButton}/>
    ...
  )
}

如果你想使用其他类的静态方法,首先导入类然后使用这样的静态方法:

import Player from 'PLAYER_FILE_LOCATION';
.
.
.
.
.
render(){
  return(
    ...
    <VideoList callback={Player.renderLoadButton}/>
    ...
  )
}