反应调用子方法的不同方式

时间:2016-11-14 20:43:17

标签: javascript reactjs

React说我们不应该尽可能使用git rm --cached <file>,我注意到你不能使用refs进行浅层渲染测试,所以我试图在可能的情况下删除ref。我有一个像这样的子组件:

refs

然后我有一个需要调用这些方法的父组件。对于class Child extends React.Component { play = () => { //play the media }, pause = () => { //pause the media }, setMedia = (newMedia) => { //set the new media } } 我可以使用带有setMedia的道具,并在新道具进入孩子时调用componentWillReceiveProps

使用setMediaplay函数,我无法做到这一点。

Ben Alpert回复了这个post并说:

  

通常,数据应该通过props传递到树下。除此之外还有一些例外(例如调用 .focus()或触发一次性动画并不真正改变状态)但随时都有你揭露了一个名为&#34; set&#34;的方法,道具通常是更好的选择。尝试做到这一点,以便内部输入组件担心它的大小和外观,以便它的祖先没有。

调用子函数的最佳方法是什么?

  1. pauseplay()方法可以从refs中调用,因为它们不像pause()那样改变状态,并且对其他具有参数的函数使用props。
  2. 通过传递方法名称来调用子函数,尽管这看起来很简单,而且复杂得多:

    focus()
  3. 在子组件中执行此操作:class Child extends React.Component { play = () => { //play the media }, pause = () => { //pause the media }, setMedia = (newMedia) => { //set the new media }, _callFunctions = (functions) => { if (!functions.length) { return; } //call each new function functions.forEach((func) => this[func]()); //Empty the functions as they have been called this.props.updateFunctions({functions: []}); } componentWillReceiveProps(nextProps) { this._callFunctions(nextProps.functions); } } class Parent extends React.Component { updateFunctions = (newFunctions) => this.setState({functions: newFunctions}); differentPlayMethod = () => { //...Do other stuff this.updateFunctions("play"); } render() { return ( <Child updateFunctions={this.updateFunctions}/> ); } } 这个问题是我们将一个方法暴露(复制)到另一个不应该真正了解它的组件......

  4. 这是最好的方法吗?

    我目前正在使用方法2,我不是很喜欢它。

    为了覆盖子函数,我也做了类似于上面的操作。我应该只使用refs吗?

2 个答案:

答案 0 :(得分:2)

尝试从父级传递数据和函数,而不是调用子函数。除了组件,您还可以导出提供必要状态/函数的包装器或更高阶函数。

let withMedia = Wrapped => {
  return class extends React.Component {
    state = { playing: false }
    play() { ... }
    render() {
      return (
        <Wrapped 
          {...this.state} 
          {...this.props} 
          play={this.play}
        />
      )
    }
  }
}

然后在您的父组件中:

import { Media, withMedia } from 'your-library'

let Parent = props =>
  <div>
    <button onClick={props.play}>Play</button>
    <Media playing={props.playing} />
  </div>

export default withMedia(Parent)

答案 1 :(得分:0)

尽可能保持状态本地化,但不要将其分布在多个组件上。如果您需要有关父级和子级当前是否正在播放的信息,请将状态保留在父级中。

这为您留下了更清晰的状态树和道具:

&#13;
&#13;
class Child extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.props.togglePlay}>Child: Play/Pause</button>
        <p>Playing: {this.props.playing ? 'Yes' : 'No'}</p>
      </div>
    );
  }
}

class Parent extends React.Component {
  constructor(props) {
    super(props);
    
    this.togglePlay = this.togglePlay.bind(this);
    
    this.state = {
      playing: false
    };
  }
  
  togglePlay() {
    this.setState({
      playing: !this.state.playing
    });
  }
  
  render() {
    return (
      <div>
        <button onClick={this.togglePlay}>Parent: Play/Pause</button>
        <Child togglePlay={this.togglePlay} playing={this.state.playing} />
      </div>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById('app')
);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'></div>
&#13;
&#13;
&#13;