aesthetic-suite / framework

🎨 Aesthetic is an end-to-end multi-platform styling framework that offers a strict design system, robust atomic CSS-in-JS engine, a structural style sheet specification (SSS), a low-runtime solution, and much more!
https://aestheticsuite.dev
MIT License
203 stars 5 forks source link

Component extension #23

Closed jacksenior closed 6 years ago

jacksenior commented 6 years ago
class Bar extends React.Component {
  getString() {
    return 'Foo';
  }

  render() {
    return <div className={this.props.styles.string}>{this.getString()})</div>
  }
}

export default withStyles({
  string: {
    backgroundColor: 'red',
  },
},
{
  styleName: 'Bar',
  extendable: true,
})(Bar);
export default class Foo extends Bar  {
  getString() {
    return 'Foo';
  }
}

Given then example above I'm attempting to extend a react component to share the render and common methods. However it appears that only the styles can be extended as this results in the equivalent of this.props.styles.string throwing the error, TypeError: Cannot read property 'string' of undefined when the extended component Foo is ran.

Is there a way to extend the base component but not the styles or is this a bad pattern?

milesj commented 6 years ago

It's not a bad pattern but in the context of React, composition over inheritance is preferred. For example, instead of sharing a render() through inheritance, you can create an SFC and render that instead.

function Baz({ children, styles, ...props }) {
  return <div {...props} className={styles.string}>{children}</div>;
}

export default withStyles({
  string: {
    backgroundColor: 'red',
  },
},
{
  styleName: 'Baz',
})(Baz);

class Bar extends React.Component {
  getString() {
    return 'Bar';
  }

  render() {
    return <Baz>{this.getString()}</Baz>
  }
}

class Foo extends Bar  {
  getString() {
    return 'Foo';
  }

  render() {
    return <Baz>{this.getString()}</Baz>
  }
}
jacksenior commented 6 years ago

Thanks for getting back to me, that's exactly what I ended up doing

milesj commented 6 years ago

Cool, glad you got it working!