最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React class methods overriding - Stack Overflow

programmeradmin3浏览0评论

I am trying to create some kind of class composition in react:

class Entity {
  constructor(props) {
    super(props);
  }
  renderPartial() {
    return (<div>Entity</div>)
  }
  render() {
    return (<div>header {this.renderPartial()}</div>);
  }
}

class Person extends Entity{
  constructor(props) {
    super(props);
  }
  renderPartial() {
    return (<div>Person</div>)
  }
}

class Manager extends Person {
  constructor(props) {
    super(props);
  }

  renderPartial() {
    return (<div>Manager</div>)
  }
}

In the following example Person extends from Entity class. And the goal here is to render partial content inside of the extended class. So for the simplicity sake I just render class name. This way everything works fine with Person class and it renders its text. But when I extend Manager from Person it writes <div>Person</div> and I can't understand why. Is there any way to override renderPartial inside of the Manager class?

I am trying to create some kind of class composition in react:

class Entity {
  constructor(props) {
    super(props);
  }
  renderPartial() {
    return (<div>Entity</div>)
  }
  render() {
    return (<div>header {this.renderPartial()}</div>);
  }
}

class Person extends Entity{
  constructor(props) {
    super(props);
  }
  renderPartial() {
    return (<div>Person</div>)
  }
}

class Manager extends Person {
  constructor(props) {
    super(props);
  }

  renderPartial() {
    return (<div>Manager</div>)
  }
}

In the following example Person extends from Entity class. And the goal here is to render partial content inside of the extended class. So for the simplicity sake I just render class name. This way everything works fine with Person class and it renders its text. But when I extend Manager from Person it writes <div>Person</div> and I can't understand why. Is there any way to override renderPartial inside of the Manager class?

Share Improve this question asked Jan 26, 2016 at 0:56 Alex BerdyshevAlex Berdyshev 7612 gold badges7 silver badges21 bronze badges 2
  • Seems fine to me. Maybe a typo in the method name? – Bergi Commented Jan 26, 2016 at 0:59
  • @Bergi I am starting to think that this approach isn't working with react( Because in es6 it works fine gist.github.com/berdof/a54d43c289bf6787ad02 – Alex Berdyshev Commented Jan 26, 2016 at 1:10
Add a comment  | 

2 Answers 2

Reset to default 15

Don't use inheritance in React (other than extending React.Component). It's not the recommended approach. More on this here. (See also here.)

If you need outer and inner components, you can use this.props.children. e.g.

render() {
  return <div>header {this.props.children}</div>;
}

This allows you to do the following:

<Entity>
  <Person />
</Entity>

But usually even this is unnecessary. Simply split your components into smaller pieces. e.g.

<div>
  <Header />
  <Person />
</div>

Small, modular components are much easier to manage than gargantuan objects with long inheritance chains.

There is a problem with your code posted above: super() should only be used in a derived constructor. Since Entity doesn't extend any class, super() doesn't make any sense in this context, and throws a syntax error using ES6 transpiled with babel.

Rendering your code in a browser will also produce a warning: "React component classes must extend React.Component" - your classes should extend React.Component, as below.

As mentioned below, inheritance is not the recommended or 'React' way to share code between components (composition is the way forward). For something as simple as your example, you would probably want to use a single component multiple times with different props:

class Entity extends React.Component {
  render() {
    <div>header {this.props.headerType}</div>
  }
}

Entity.defaultProps = {
  headerType: 'Entity'
}

<Entity /> // renders <div>header Entity</div>
<Entity entityType ='Person' /> // renders <div>header Person</div>
<Entity entityType ='Manager' /> // renders <div>header Manager</div>

If you want to retain your named components, you can simply wrap the <Header> component and set the prop:

class Person extends React.Component {
  render() {
    <Entity entityType='Person' />
  }
}

<Entity /> // renders <div>header Entity</div>

However, for more complex code reuse, you might want to explore higher order components - essentially functions that wrap and return components.

let entityComponent = function(Component) {

  class EntityComponent extends React.Component {

    render() {
      return (
        <div>
          header <Component {...this.props} />
        </div>
      );
    }

  }

  EntityComponent.defaultProps = {
    headerType: 'Entity'
  }

  return EntityComponent;

}

class Entity extends React.Component {

  render() {
    return (
      <span>{this.props.headerType}</span>
    );
  }

}

Entity = entityComponent(Entity);

<Entity /> // renders <div>header <span>Entity</span></div>

class Person extends React.Component {

  render() {
    return (
      <span>{this.props.headerType}</span>
    );
  }

}

Person = entityComponent(Person);

<Person headerType='Person' /> // renders <div>header <span>Person</span></div>

A combination of these techniques should enable you to achieve what you want!

发布评论

评论列表(0)

  1. 暂无评论