【问题标题】:React Component Inheritance to use parent method and child methodReact Component Inheritance 使用父方法和子方法
【发布时间】:2020-03-18 02:38:43
【问题描述】:

背景

我创建了一个功能齐全的组件。组件有state和props,里面有很多方法。根据操作系统(ios / android),我的组件应该以不同的方式工作。所以我通过if 语句解决了这个问题,如下所示。

if( platform.os == 'ios') { ... } else { ... }

问题是随着代码量的增加,可读性出现问题,我决定为IOS和Android分别制作一个组件。首先想到的是继承,因为 ES6 和 Typescript 支持类。概念图是这样的。

但是,React does not recommend inheritance。所以我只是打算将 props 覆盖的函数交给 SpeechIOS 组件的渲染函数中的 Speech 组件。

代码如下。

Speech.tsx

type Props = {
  team: number,
  onSpeechResults: (result: string) => void
  ...
}
type States = {
  active: boolean;
  error: string;
  result: string;
  ...
};

export default class Speech extends Component<Props,States> {
  state = { ... };
  constructor(props: Props) {
    super(props);
    ...
  }

  // render
  render() {
    ...
    return (
      <ImageBackground source={require("../images/default-background.jpeg")} style={styles.full}>
        ...
      </ImageBackground>
    );
  }
  sendCommand = (code: number, speed: number, callback?: () => void) => { ... }
  getMatchedSpell = (spellWord: string): { code: number, speed: number } => { ... }
  onSpeechResults(e: Voice.Results) { ... };
  ...
}

SpeechIOS.tsx

import Speech from './Speech';

type Props = {}
type States = {}
export default class SpeechIOS extends Component<Props,States> {
  constructor(props: Props) {
    super(props);
    ...
  }

  // render
  render() {
    ...
    return ( <Speech team="1" onSpeechResults={this.onSpeechResults}></Speech> );
  }

  sayHello() {
    console.log("Hello!!");
  }

  // I want that Speech Component call this onSpeechResults function
  onSpeechResults(result: string) {
    this.setState({...});
    let temp = this.getMatchedSpell( ... ); // which is in Speech Component
    this.sendCommand( 10, 100 ... ); // which is in Speech Component
    this.sayHello(); // which is in SpeechIOS component only
    ... other things..
  };
}

问题。

如您所见,SpeechIOS 组件中的onSpeechResults 使用了 Speech 组件和 SpeechIOS 组件中的一些功能。

那么,如何解决这个问题呢?我应该使用继承吗?

【问题讨论】:

    标签: javascript reactjs typescript inheritance


    【解决方案1】:

    您可以为此目的使用 React.createRef。 下面是一个示例代码。

    import Speech from './Speech';
    
    type Props = {}
    type States = {}
    export default class SpeechIOS extends Component<Props, States> {
        constructor(props: Props) {
            super(props);
            this.speech = React.createRef();
        }
    
        // render
        render() {
            ...
            return (<Speech ref={this.speech} team="1" onSpeechResults={this.onSpeechResults}></Speech>);
        }
    
        sayHello() {
            console.log("Hello!!");
        }
    
        // I want that Speech Component call this onSpeechResults function
        onSpeechResults(result: string) {
            this.setState({ ...});
            let temp = this.speech.current.getMatchedSpell(... ); // which is in Speech Component
            this.sendCommand(10, 100 ... ); // which is in Speech Component
            this.sayHello(); // which is in SpeechIOS component only
            ...other things..
        };
    }
    

    【讨论】:

    • 好主意。谢谢你
    【解决方案2】:

    您应该定义一个顶级组件来定义共享的 props 和方法,并使用它们来呈现您的 ios 或 android 组件。把道具和方法传给孩子。这是在反应中优于继承的组合。示例:

    class Speech extends React.Component {
    
      state ={shared: 'state'}
    
      sharedMethod = () => {
        this.setState({blah: 'blah})
      }
    
      render() {
        const Root = Platform.select({
          ios: SpeechIOS,
          android: SpeechAndroid
        })
    
        return <Root onClick={this.sharedMethod}  shared={this.state.shared}/>
      }
    
    }
    

    【讨论】:

    • 但是如何在 Speech Component 中调用 SpeechIOS 中的函数呢?
    • 我应该将所有共享方法和状态作为道具传递给 SpeechIOS 吗??.. 我认为我的代码会太长太复杂。
    • 只传递你需要的东西。必要时使用对象传播。或者调查有关使用 React Context 的文档。如果您发现自己需要从父级调用子方法,那么您就是在冒险进入命令式领域,应该重新评估您的依赖方向。 stackoverflow.com/questions/37949981/…
    【解决方案3】:

    或者,将任何通用逻辑分解为一个实用函数,如SpeechUtil.ts,一个包含此共享逻辑和每个实用函数的全新文件,并导出它们。然后,每个组件分别导入它们。这样可以确保如果您更新该逻辑,它会影响两个组件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-29
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 2018-07-20
      • 2018-10-28
      • 1970-01-01
      相关资源
      最近更新 更多